• This notebook shows the sensitivity analysis of temporal covariance analysis from CVTKPY.

1 How Temporal Covariacnes change with depth filtering

1.1 Create VCF files with different maximum depth filtering

  • Filter by depth from the MD7000 VCF file using bcftools:
  • Depths are based on 14 populations
# Use bcftools to filter by Max Depth
bcftools filter -i 'INFO/DP<2000' 3pops.MD7000_NS0.5_maf05.vcf.gz > 3pops.MD2000.maf05.vcf
bcftools filter -i 'INFO/DP<3000' 3pops.MD7000_NS0.5_maf05.vcf.gz > 3pops.MD3000.maf05.vcf
bcftools filter -i 'INFO/DP<4000' 3pops.MD7000_NS0.5_maf05.vcf.gz > 3pops.MD4000.maf05.vcf
bcftools filter -i 'INFO/DP<5000' 3pops.MD7000_NS0.5_maf05.vcf.gz > 3pops.MD5000.maf05.vcf
bcftools filter -i 'INFO/DP<6000' 3pops.MD7000_NS0.5_maf05.vcf.gz > 3pops.MD6000.maf05.vcf

gzip 3pops.MD2000.maf05.vcf
gzip 3pops.MD3000.maf05.vcf
gzip 3pops.MD4000.maf05.vcf
gzip 3pops.MD5000.maf05.vcf
gzip 3pops.MD6000.maf05.vcf

1.2 Run CVTKPY on data with different filtering (Max Depth 2000-7000)

  • Covariances from Max Depth 2000 ~ 7000
  • 1M window for MD2000-6000, 100k for MD7000

1.2.1 Max Depth = 2000 (1M-window)

pops<-c("PWS","TB","SS")
covs<-data.frame()
Variance<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_maf05_temp_cov_matrix_",pops[p],"_1M.csv"))
    cov<-cov[,-1]
    #CI file
    ci<-read.csv(paste0("../cvtk_analysis/MD2000_maf05_",pops[p],"_Cov_CIs_bootstrap5000_1Mwindow.csv"))
    ci<-ci[,-1]
        
    #reshape the matrix
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
        
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
        }
    }
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    #remove the redundant values
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    #assign the starting time period and covering period values
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
        
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    #vars$series<-c("1991","1991","1996")
        
    #assign population name
    covar$location<-pops[p]
    vars$location<-pops[p]
        
    #attach ci info
    covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
    covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
        
    #combine in to one matrix
    covs<-rbind(covs, covar)
    Variance<-rbind(Variance, vars)
}
Variance$depth<-"MD2000"
Variances<-Variance
xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

ggplot(data=covs, aes(x=year, y=value, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=value,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+ggtitle("Max Depth = 2000")+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("1991-","1996-"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])
ggsave(paste0("../Output/COV_analysis/MD2000_covs.png"),width = 4.7, height = 3, dpi=300)

1.2.2 MD3000-MD7000

pops<-c("PWS","TB","SS")
mds<-c("MD3000","MD4000","MD5000","MD6000","MD7000")
xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

for (m in 1: length(mds)){
    covs<-data.frame()
    Variance<-data.frame()
    if(m==5){
        for (p in 1: length(pops)){
            cov<-read.csv(paste0("../cvtk_analysis/",mds[m],"_maf05_temp_cov_matrix_",pops[p],".csv"))
            cov<-cov[,-1]
            ci<-read.csv(paste0("../cvtk_analysis/",mds[m],"_maf05_",pops[p],"_Cov_CIs_bootstrap5000.csv"))
            ci<-ci[,-1]
        
            mat1<-cov[1:3,]
            mat2<-cov[4:6,]
            
            covdf<-data.frame()
            k=1
            for (i in 1:nrow(mat1)){
                for (j in 1:ncol(mat1)){
                    covdf[k,1]<-mat2[i,j]
                    covdf[k,2]<-mat1[i,j]
                    k=k+1
                    }
            }
            colnames(covdf)<-c("label","value")
        covdf$value<-as.numeric(covdf$value)
        covar<-covdf[grep("cov",covdf$label),]
        vars<-covdf[grep("var",covdf$label),]
            
        if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
        if (pops[p]=="SS") covar<-covar[c(1,2,4),]
            
        #assign the starting time period and covering period values
        covar$year<-c(1,2,2)
        covar$series<-c("1991","1991","1996")
            
        vars$year<-c("1991-1996","1996-2006","2006-2017")
            
        #assign population name
        covar$location<-pops[p]
        vars$location<-pops[p]
            
        #attach ci info
        covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
        covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
            
        #combine in to one matrix
        covs<-rbind(covs, covar)
        Variance<-rbind(Variance, vars)
        }
    }
    else{
        for (p in 1: length(pops)){
        cov<-read.csv(paste0("../cvtk_analysis/",mds[m],"_maf05_temp_cov_matrix_",pops[p],"_1M.csv"))
        cov<-cov[,-1]
        ci<-read.csv(paste0("../cvtk_analysis/",mds[m],"_maf05_",pops[p],"_Cov_CIs_bootstrap5000_1Mwindow.csv"))
        ci<-ci[,-1]
        
        mat1<-cov[1:3,]
        mat2<-cov[4:6,]
        
        covdf<-data.frame()
        k=1
        for (i in 1:nrow(mat1)){
            for (j in 1:ncol(mat1)){
                covdf[k,1]<-mat2[i,j]
                covdf[k,2]<-mat1[i,j]
                k=k+1
            }
        }
        
        colnames(covdf)<-c("label","value")
        covdf$value<-as.numeric(covdf$value)
        covar<-covdf[grep("cov",covdf$label),]
        vars<-covdf[grep("var",covdf$label),]
            
        if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
        if (pops[p]=="SS") covar<-covar[c(1,2,4),]
            
        #assign the starting time period and covering period values
        covar$year<-c(1,2,2)
        covar$series<-c("1991","1991","1996")
            
        vars$year<-c("1991-1996","1996-2006","2006-2017")
            
        #assign population name
        covar$location<-pops[p]
        vars$location<-pops[p]
            
        #attach ci info
        covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
        covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
            
        #combine in to one matrix
        covs<-rbind(covs, covar)
        Variance<-rbind(Variance, vars)
        }
    }
        
    Variance$depth<-mds[m]
    Variances<-rbind(Variances,Variance)
    ggplot(data=covs, aes(x=year, y=value, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=value,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+ggtitle(mds[m])+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("1991-","1996-"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])
    ggsave(paste0("../Output/COV_analysis/",mds[m],"_covs.png"),width = 4.7, height = 3, dpi=300)    
}

Variances_org<-Variances

1.3 Plot Variances

seqcols<-sequential_hcl(6, palette="Red-Blue")
#reverse the order
seqcols<-rev(seqcols)
colnames(Variances)[2]<-"Variance"
ggplot(Variances, aes(x=year, y=Variance, fill=depth))+
    facet_wrap(~location, ncol=1)+
    geom_bar(stat="identity", position=position_dodge(width=0.8))+
    theme_bw()+geom_hline(yintercept = 0, color="gray30", size=0.3)+
    scale_fill_manual(values=seqcols, name="Max depth")
ggsave("../Output/COV_analysis/variances_byMaxDepthFilter.png", width = 7, height=6, dpi=300)

1.4 Diagnostic plots from CVTKPY

1.4.1 MD7000 original diagnostic plots (correction vs. none)

1.4.2 MD2000

1.4.3 MD3000

1.5 MD4000




2 Create new VCF files with new filtering (MD3000 & MD2000)

2.1 Create quality filtered snps for 3 pops at FARM, and filter to DP<2000 locally (FARM does not have the latest bcftools)

for (i in n){
    sink(paste0("../Data/Slurmscripts/0.filter_raw_",i,".sh"))
    cat("#!/bin/bash -l\n")
    cat(paste0("#SBATCH --job-name=filter",i," \n"))
    cat(paste0("#SBATCH --mem=16G \n")) 
    cat(paste0("#SBATCH --ntasks=8 \n")) 
    cat(paste0("#SBATCH -e filter",i,".err  \n"))
    cat(paste0("#SBATCH --time=144:00:00  \n"))
    cat(paste0("#SBATCH -p high  \n"))
    cat("\n\n")
    cat('module load samtools \n') 
    cat('module load bcftools \n\n') 
    
    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/timeseries.txt -m2 -M2 -v snps /home/jamcgirr/ph/data/combine_gvcfs/raw_variants_chr",i,"_1.vcf | bcftools filter -Oz -i 'MQ>30 && QUAL>20' -o /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i,"_1.vcf.gz  \n"))
    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/timeseries.txt -m2 -M2 -v snps /home/jamcgirr/ph/data/combine_gvcfs/raw_variants_chr",i,"_2.vcf | bcftools filter -Oz -i 'MQ>30 && QUAL>20' -o /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i,"_2.vcf.gz  \n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i,"_1.vcf.gz\n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i,"_2.vcf.gz \n\n")) 
    
    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/timeseries.txt -m2 -M2 -v snps /home/jamcgirr/ph/data/combine_gvcfs/raw_variants_chr",i+1,"_1.vcf | bcftools filter -Oz -i 'MQ>30 && QUAL>20' -o /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i+1,"_1.vcf.gz  \n"))
    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/timeseries.txt -m2 -M2 -v snps /home/jamcgirr/ph/data/combine_gvcfs/raw_variants_chr",i+1,"_2.vcf | bcftools filter -Oz -i 'MQ>30 && QUAL>20' -o /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i+1,"_2.vcf.gz  \n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i+1,"_1.vcf.gz\n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/VCF/qual_filtered_snps_chr",i+1,"_2.vcf.gz \n\n")) 
sink(NULL)
}  


# create bash scripts to run locally

sink(paste0("../Data/Slurmscripts/1.filter_byDepth.sh"))
cat("#!/bin/bash \n")
for (i in 1:26){
    cat(paste0("bcftools annotate -x INFO/DP /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD3000/qual_filtered_snps_chr",i,"_1.vcf.gz |bcftools +fill-tags -- -t 'INFO/DP=sum(DP)' | bcftools filter -Oz -i 'INFO/DP>471 && INFO/DP<3000' -o /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD3000/filtered_snps_MD3000_chr",i,"_1.vcf.gz   \n"))
     cat(paste0("bcftools annotate -x INFO/DP /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD3000/qual_filtered_snps_chr",i,"_2.vcf.gz | bcftools +fill-tags -- -t 'INFO/DP=sum(DP)' | bcftools filter -Oz -i 'INFO/DP>471 && INFO/DP<3000' -o /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD3000/filtered_snps_MD3000_chr",i,"_2.vcf.gz   \n"))
    
}
sink(NULL)


sink(paste0("../Data/Slurmscripts/1.filter_byDepth2.sh"))
cat("#!/bin/bash \n")
for (i in 1:26){
    cat(paste0("bcftools annotate -x INFO/DP /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD2000/qual_filtered_snps_chr",i,"_1.vcf.gz |bcftools +fill-tags -- -t 'INFO/DP=sum(DP)' | bcftools filter -Oz -i 'INFO/DP>471 && INFO/DP<2000' -o /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD2000/filtered_snps_MD2000_chr",i,"_1.vcf.gz   \n"))
     cat(paste0("bcftools annotate -x INFO/DP /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD2000/qual_filtered_snps_chr",i,"_2.vcf.gz | bcftools +fill-tags -- -t 'INFO/DP=sum(DP)' | bcftools filter -Oz -i 'INFO/DP>471 && INFO/DP<2000' -o /Users/kahotisthammer/Projects/PacHerring/Data/new_vcf/MD2000/filtered_snps_MD2000_chr",i,"_2.vcf.gz   \n"))
    
}
sink(NULL)

2.2 Merge all vcfs

sink(paste0("../Data/Slurmscripts/2.Merge_MD3000VCFs.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=mergeVCFs \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n")) 
cat(paste0("#SBATCH -e mergeVCFs.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 
for (i in 1:26){
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/filtered_snps_MD3000_chr",i,"_1.vcf.gz \n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/filtered_snps_MD3000_chr",i,"_2.vcf.gz \n"))
}
cat("\n")
cat("bcftools concat -o /home/ktist/ph/data/new_vcf/MD3000/merged_filtered_snps_MD3000.bcf -O b --threads 24 ") 
for (i in 1:26){
    cat(paste0("/home/ktist/ph/data/new_vcf/MD3000/filtered_snps_MD3000_chr",i,"_1.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/filtered_snps_MD3000_chr",i,"_2.vcf.gz "))
}
cat("\n")
cat("bcftools index /home/ktist/ph/data/new_vcf/MD3000/merged_filtered_snps_MD3000.bcf \n")
sink(NULL)


sink(paste0("../Data/Slurmscripts/2.Merge_MD2000VCFs.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=mergeVCFs \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n")) 
cat(paste0("#SBATCH -e mergeVCFs.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 
for (i in 1:26){
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/filtered_snps_MD2000_chr",i,"_1.vcf.gz \n"))
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/filtered_snps_MD2000_chr",i,"_2.vcf.gz \n"))
}
cat("\n")
cat("bcftools concat -o /home/ktist/ph/data/new_vcf/MD2000/merged_filtered_snps_MD2000.bcf -O b --threads 24 ") 
for (i in 1:26){
    cat(paste0("/home/ktist/ph/data/new_vcf/MD2000/filtered_snps_MD2000_chr",i,"_1.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/filtered_snps_MD2000_chr",i,"_2.vcf.gz "))
}
cat("\n")
cat("bcftools index /home/ktist/ph/data/new_vcf/MD2000/merged_filtered_snps_MD2000.bcf \n")
sink(NULL)

2.3 Subset vcf into 11 populations (grouped by unique(location:year)) and filter for 50% genotyping rate

pop_info<-read.csv("../Data/Sample_metadata_892pops.csv")
pops<-unique(pop_info$Population.Year) 
pops<-pops[grep("PWS|SS|TB", pops)]
popsize<-data.frame(table(pop_info$Population.Year))

# MD3000
sink(paste0("../Data/Slurmscripts/3.SubsetVCFs_filterNS0.5_MD3000.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=subset \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n")) 
cat(paste0("#SBATCH -e subsetVCFs.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")
cat('module load bcftools \n\n') 
for (i in 1:length(pops)){
    n<-popsize$Freq[popsize$Var1==pops[i]]/2

    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/", pops[i], ".txt /home/ktist/ph/data/new_vcf/MD3000/merged_filtered_snps_MD3000.bcf | bcftools +fill-tags -- -t all,'NS' | bcftools filter -Oz -i 'NS>",n,"' >  /home/ktist/ph/data/new_vcf/MD3000/",pops[i],"_filtered_MD3000.vcf.gz \n") )
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/MD3000/",pops[i],"_filtered_MD3000.vcf.gz \n"))
}
sink(NULL)

# MD2000
sink(paste0("../Data/Slurmscripts/3.SubsetVCFs_filterNS0.5_MD2000.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=subset \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n")) 
cat(paste0("#SBATCH -e subsetVCFs.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")
cat('module load bcftools \n\n') 
for (i in 1:length(pops)){
    n<-popsize$Freq[popsize$Var1==pops[i]]/2

    cat(paste0("bcftools view -S /home/ktist/ph/data/new_vcf/population/", pops[i], ".txt /home/ktist/ph/data/new_vcf/MD2000/merged_filtered_snps_MD2000.bcf | bcftools +fill-tags -- -t all,'NS' | bcftools filter -Oz -i 'NS>",n,"' >  /home/ktist/ph/data/new_vcf/MD2000/",pops[i],"_filtered_MD2000.vcf.gz \n") )
    cat(paste0("bcftools index /home/ktist/ph/data/new_vcf/MD2000/",pops[i],"_filtered_MD2000.vcf.gz \n"))
}
sink(NULL)

2.4 Find intersecting loci

#MD3000
sink(paste0("../Data/Slurmscripts/4.Isec_MD3000_3pops.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=isec3pops2 \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH -e isec3pops2.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 

cat(paste0("bcftools isec -n=11 -p isec3pops_MD3000 --threads 24  /home/ktist/ph/data/new_vcf/MD3000/PWS17_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/PWS91_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/PWS96_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/SS06_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/SS17_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/SS96_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/TB06_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/TB17_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/TB91_filtered_MD3000.vcf.gz /home/ktist/ph/data/new_vcf/MD3000/TB96_filtered_MD3000.vcf.gz  \n"))
sink(NULL)


#MD2000
sink(paste0("../Data/Slurmscripts/Isec_MD2000_3pops.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=isec3pops \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH -e isec3pops.err  \n"))
cat(paste0("#SBATCH --time=72:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 

cat(paste0("bcftools isec -n=11 -p isec3pops_MD2000 --threads 24 /home/ktist/ph/data/new_vcf/MD2000/PWS07_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/PWS17_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/PWS91_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/PWS96_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/SS06_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/SS17_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/SS96_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/TB06_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/TB17_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/TB91_filtered_MD2000.vcf.gz /home/ktist/ph/data/new_vcf/MD2000/TB96_filtered_MD2000.vcf.gz  \n"))
    
sink(NULL)

2.5 Filter to the intersecting loci

#MD3000
sink(paste0("../Data/Slurmscripts/5.FilterMD3000_3pops.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=3kfil \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n"))
cat(paste0("#SBATCH -e 3kfil.err  \n"))
cat(paste0("#SBATCH --time=144:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 
cat("bcftools view -S /home/ktist/ph/data/new_vcf/population/timeseries.txt -R /home/ktist/isec3pops_MD3000/sites.txt -Oz --threads 24  /home/ktist/ph/data/new_vcf/MD3000/merged_filtered_snps_MD3000.bcf >  /home/ktist/ph/data/new_vcf/MD3000/3pops_MD3000_NS0.5.vcf.gz \n")

cat("bcftools index /home/ktist/ph/data/new_vcf/3pops_MD3000_NS0.5.vcf.gz \n")

cat("bcftools filter -Oz --threads 24 -i 'INFO/AF>0.05' /home/ktist/ph/data/new_vcf/3pops_MD3000_NS0.5.vcf.gz -o /home/ktist/ph/data/new_vcf/MD2000/3pops_MD3000_maf05.vcf.gz \n")

cat("bcftools index /home/ktist/ph/data/new_vcf/MD3000/3pops_MD3000_maf05.vcf.gz \n")
sink(NULL)

#MD2000
sink(paste0("../Data/Slurmscripts/FilterMD2000_3pops2.sh"))
cat("#!/bin/bash -l\n")
cat(paste0("#SBATCH --job-name=2kFil \n"))
cat(paste0("#SBATCH --mem=16G \n")) 
cat(paste0("#SBATCH --ntasks=8 \n")) 
cat(paste0("#SBATCH --nodes=4 \n")) 
cat(paste0("#SBATCH -e 2kFil.err  \n"))
cat(paste0("#SBATCH --time=144:00:00  \n"))
cat(paste0("#SBATCH -p high  \n"))
cat("\n\n")

cat('module load bcftools \n\n') 
cat("bcftools view -Oz -S /home/ktist/ph/data/new_vcf/population/timeseries.txt --threads 24  -R /home/ktist/isec3pops_MD2000/sites.txt /home/ktist/ph/data/new_vcf/MD2000/merged_filtered_snps_MD2000.bcf  > /home/ktist/ph/data/new_vcf/MD2000/3pops_MD2000_NS0.5.vcf.gz \n")

cat("bcftools index /home/ktist/ph/data/new_vcf/MD2000/3pops_MD2000_NS0.5.vcf.gz  \n")

cat("bcftools filter -Oz --threads 24 -i 'INFO/AF>0.05' /home/ktist/ph/data/new_vcf/MD2000/3pops_MD2000_NS0.5.vcf.gz -o /home/ktist/ph/data/new_vcf/MD2000/3pops_MD2000_maf05.vcf.gz \n")
cat("bcftools index /home/ktist/ph/data/new_vcf/MD2000/3pops_MD2000_maf05.vcf.gz \n")

sink(NULL)

2.6 RUN cvtk with the new MD2000 vcf file

*(351,820 loci)

pops<-c("PWS","TB","SS")
covs<-data.frame()
Variance<-data.frame()
for (p in 1: length(pops)){
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_3pops_maf05_temp_cov_matrix_",pops[p],"_1m.csv"))
    ci<-read.csv(paste0("../cvtk_analysis/MD2000_3pops_maf05_",pops[p],"_Cov_CIs_bootstrap5000_1mwindow.csv"))
    ci<-ci[,-1]
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
    }}
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
    
    #remove the redundant values
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    #assign the starting time period and covering period values
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
        
    vars$year<-c("1991-1996","1996-2006","2006-2017")
        
    #assign population name
    covar$location<-pops[p]
    vars$location<-pops[p]
        
    #attach ci info
    covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
    covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
        
    #combine in to one matrix
    covs<-rbind(covs, covar)
    Variance<-rbind(Variance, vars)
}
Variance$depth<-"MD2000_new"
#VarMD2000<-Variance
xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

ggplot(data=covs, aes(x=year, y=value, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=value,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+ggtitle("Max Depth = 2000")+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("1991-","1996-"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])
ggsave(paste0("../Output/COV_analysis/MD2000_newVCF_covs.png"),width = 4.7, height = 3, dpi=300)

2.7 Plot results from MD2000 filtered down from MD70000

pops<-c("PWS","TB","SS")
covs<-data.frame()
Variance<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_maf05_temp_cov_matrix_",pops[p],"_1M.csv"))
    cov<-cov[,-1]
    #CI file
    ci<-read.csv(paste0("../cvtk_analysis/MD2000_maf05_",pops[p],"_Cov_CIs_bootstrap5000_1Mwindow.csv"))
    ci<-ci[,-1]
        
    #reshape the matrix
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
        
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
        }
    }
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    #remove the redundant values
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    #assign the starting time period and covering period values
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
        
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    #vars$series<-c("1991","1991","1996")
        
    #assign population name
    covar$location<-pops[p]
    vars$location<-pops[p]
        
    #attach ci info
    covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
    covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
        
    #combine in to one matrix
    covs<-rbind(covs, covar)
    Variance<-rbind(Variance, vars)
}
Variance$depth<-"MD2000_md7k"
VarMD2000_md7k<-Variance
xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

ggplot(data=covs, aes(x=year, y=value, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=value,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+ggtitle("Max Depth = 2000 (filtered from 7K)")+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("1991-","1996-"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])
ggsave(paste0("../Output/COV_analysis/MD2000_filteredFromMD7000_VCF_covs.png"),width = 4.7, height = 3, dpi=300)

2.8 Plot covariacne results from new MD3000 (3 pops only, 389817 loci)

pops<-c("PWS","TB","SS")
covs<-data.frame()
Variance<-data.frame()
for (p in 1: length(pops)){
    cov<-read.csv(paste0("../cvtk_analysis/MD3000_3pops_maf05_temp_cov_matrix_",pops[p],"_100k.csv"))
    cov<-cov[,-1]
    ci<-read.csv(paste0("../cvtk_analysis/MD3000_3pops_maf05_",pops[p],"_Cov_CIs_bootstrap5000_100kwindow.csv"))
    ci<-ci[,-1]
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
        }
    }
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    covar$location<-pops[p]
    vars$location<-pops[p]
    covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
    covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
    covs<-rbind(covs, covar)
    Variance<-rbind(Variance, vars)
}
Variance$depth<-"MD3000_new"
var.summary<-rbind(VarMD2000,Variance)
xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

ggplot(data=covs, aes(x=year, y=value, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=value,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+ggtitle("Max Depth = 3000")+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=ci_l, ymax=ci_u), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("1991-","1996-"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])
ggsave(paste0("../Output/COV_analysis/MD3000_newVCF_covs.png"),width = 4.7, height = 3, dpi=300)

2.9 Plot the variances of new MD2000, MD3000 & old MD2000

var.summary<-rbind(var.summary,VarMD2000_md7k)

seqcols<-sequential_hcl(5, palette="Red-Blue")
#reverse the order
seqcols<-rev(seqcols)
ggplot(var.summary, aes(x=year, y=value, fill=depth))+
    facet_wrap(~location, ncol=1)+
    geom_bar(stat="identity", position=position_dodge(width=0.8))+
    theme_bw()+ylab("Variance")+xlab('')+
    geom_hline(yintercept = 0, color="gray30", size=0.3)+
    scale_fill_manual(values=seqcols, name="Max depth")
ggsave("../Output/COV_analysis/variances_byMaxDepthFilter.png", width = 7, height=6, dpi=300)

* Variances are negative at MD3000 -> Use MD2000

3 Create population vcf files for manual CI calculation

3.1 Create a script to run bcftools

sink("Subset_vcf_byPop.sh")
cat("#!/bin/bash \n")
cat("bcftools view -Oz -S Data/popinfo/pws.txt --threads 24  Data/new_vcf/MD2000/3pops.MD2000_new.maf05.vcf.gz > Data/new_vcf/MD2000/3pops_MD2000_min417_PWS_maf05.vcf.gz \n")

cat("bcftools view -Oz -S Data/popinfo/ss.txt --threads 24  Data/new_vcf/MD2000/3pops.MD2000_new.maf05.vcf.gz > Data/new_vcf/MD2000/3pops_MD2000_min417_SS_maf05.vcf.gz \n")
cat("bcftools view -Oz -S Data/popinfo/tb.txt --threads 24  Data/new_vcf/MD2000/3pops.MD2000_new.maf05.vcf.gz > Data/new_vcf/MD2000/3pops_MD2000_min417_TB_maf05.vcf.gz \n")
sink(NULL)

3.2 Run CVTK without Diploid or Depth bias correction

pops<-c("PWS","TB","SS")
covs1<-data.frame()
Variance1<-data.frame()
for (p in 1: length(pops)){
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_min417_no_diploid_biasCorrection_temp_cov_matrix_",pops[p],".csv"))
    cov<-cov[,-1]
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
    
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
    }}
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    covar$location<-pops[p]
    vars$location<-pops[p]
    covs1<-rbind(covs1, covar)
    Variance1<-rbind(Variance1, vars)
}
Variance1$method<-"no_diploid_correction"

covs2<-data.frame()
Variance2<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_min417_no_depth_biasCorrection_temp_cov_matrix_",pops[p],".csv"))
    cov<-cov[,-1]
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
    
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
    }}
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    covar$location<-pops[p]
    vars$location<-pops[p]
    covs2<-rbind(covs2, covar)
    Variance2<-rbind(Variance2, vars)
}
Variance2$method<-"no_depth_correction"

covs3<-data.frame()
Variance3<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_min417_no_biasCorrections_temp_cov_matrix_",pops[p],".csv"))
    cov<-cov[,-1]
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
    
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
    }}
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    covar$location<-pops[p]
    vars$location<-pops[p]
    covs3<-rbind(covs3, covar)
    Variance3<-rbind(Variance3, vars)
}
Variance3$method<-"no_corrections"
Variance_all<-rbind(Variance1, Variance2, Variance3)

covs1$method<-"no_diploid_correction"
covs2$method<-"no_depth_correction"
covs3$method<-"no_corrections"

xtexts2<-c("\u0394'91-'96\n ~ \u0394'96-'06", "\u0394'96-'06\n  ~ \u0394'06-'17", "\u0394'91-'96\n  ~ \u0394'06-'17")

covs_all<-rbind(covs1,covs2, covs3)
covs_all$time<-rep(c("cov12","cov13","cov23"), 9)

ggplot(data=covs_all, aes(x=time, y=value, color=location, shape=method))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+
        theme(legend.title = element_blank(), axis.text.x = element_text(size=9))+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        scale_x_discrete(labels=xtexts2)+
    scale_color_manual(values=cols[c(2,3,1)])+
    geom_vline(xintercept = c(1.5,2.5), color="gray", size=0.2)
ggsave("../Output/COV/sensitivity_analysis_covs_no_bias_corrections.png", width = 7, height=6, dpi=300)

#with all corrections
covs<-data.frame()
Variance<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_3pops_maf05_temp_cov_matrix_",pops[p],"_100k.csv"))
    cov<-cov[,-1]
    #CI file
    ci<-read.csv(paste0("../cvtk_analysis/MD2000_3pops_maf05_",pops[p],"_Cov_CIs_bootstrap5000_100kwindow.csv"))
    ci<-ci[,-1]
        
    #reshape the matrix
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
        
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
        }
    }
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
    vars<-covdf[grep("var",covdf$label),]
        
    #remove the redundant values
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    #assign the starting time period and covering period values
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
        
    vars$year<-c("1991-1996","1996-2006","2006-2017")
    #vars$series<-c("1991","1991","1996")
        
    #assign population name
    covar$location<-pops[p]
    vars$location<-pops[p]
        
    #attach ci info
    covar$ci_l<-as.numeric(c(ci[1,2], ci[1,3],ci[2,3]))
    covar$ci_u<-as.numeric(c(ci[4,2], ci[4,3],ci[5,3]))
        
    #combine in to one matrix
    covs<-rbind(covs, covar)
    Variance<-rbind(Variance, vars)
}

Variance$method<-"both correction"
Variance_all<-rbind(Variance_all, Variance)

ggplot(Variance_all, aes(x=year, y=value, fill=method))+
    facet_wrap(~location, ncol=1)+
    geom_bar(stat="identity", position=position_dodge(width=0.8))+
    theme_bw()+ylab('Variance')+xlab('')+
    geom_hline(yintercept = 0, color="gray30", size=0.3)+
    scale_fill_manual(values=seqcols, name="Bias correction applied")
ggsave("../Output/COV_analysis/sensitivity_analysis_vars_no_bias_corrections.png", width = 7, height=6, dpi=300)

  • Calculate CIs using the ‘standard’ bootstrap method in cvtk to avoid being off center

3.3 Plots COVs and CIs from the ‘standard’ bootstrap method

pops<-c("PWS","TB","SS")
covs<-data.frame()
for (p in 1: length(pops)){
    #covariance output file
    cov<-read.csv(paste0("../cvtk_analysis/MD2000_3pops_maf05_temp_cov_matrix_",pops[p],"_100k.csv"))
    cov<-cov[,-1]
        
    #reshape the matrix
    mat1<-cov[1:3,]
    mat2<-cov[4:6,]
        
    covdf<-data.frame()
    k=1
    for (i in 1:nrow(mat1)){
        for (j in 1:ncol(mat1)){
            covdf[k,1]<-mat2[i,j]
            covdf[k,2]<-mat1[i,j]
            k=k+1
        }
    }
    colnames(covdf)<-c("label","value")
    covdf$value<-as.numeric(covdf$value)
    covar<-covdf[grep("cov",covdf$label),]
        
    #remove the redundant values
    if (pops[p]!="SS") covar<-covar[!duplicated(covar[, 2]),] 
    if (pops[p]=="SS") covar<-covar[c(1,2,4),]
        
    #assign the starting time period and covering period values
    covar$year<-c(1,2,2)
    covar$series<-c("1991","1991","1996")
        
    #assign population name
    covar$location<-pops[p]
    
    #combine in to one matrix
    covs<-rbind(covs, covar)
}

covs$time<-rep(c("cov12","cov13","cov23"), 3)
colnames(covs)[2]<-"cov"

# 95% confidence intervals (calculated from the 'straps' returned from bootstrap_cov2() ci=1.96*sd(straps))
time<-c("cov12","cov13","cov23")

covs$ci<-NA
for (i in 1:length(pops)){  
     if (i!=3){
        df<-read.csv(paste0("../cvtk_analysis/MD2000_",pops[i],"_CIs_100kwindow.csv"), header=F)
        covs$ci[covs$location==pops[i]&time=='cov12']<-df[1,2]
        covs$ci[covs$location==pops[i]&time=='cov13']<-df[1,3]
        covs$ci[covs$location==pops[i]&time=='cov23']<-df[2,3]
    }
    if (p==3) {
        df<-read.csv(paste0("../cvtk_analysis/MD2000_",pops[i],"_CIs_100kwindow.csv"), header=F)
        covs$ci[covs$location==pops[i]&time=='cov23']<-df[1,2] 
    }
}

xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\n  ~ \u03942006-2017")

ggplot(data=covs, aes(x=year, y=cov, color=location, shape=series, group=interaction(location, series)))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        geom_line(data=covs, aes(x=year, y=cov,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+
        theme(legend.title = element_blank())+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=cov-ci, ymax=cov+ci), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_shape_manual(values=c(16,17),labels=c("\u0394'91-'96~","\u0394'96-'06~"))+
        scale_x_continuous(breaks = c(1,2), labels=xtexts)+
        scale_color_manual(values=cols[c(2,3,1)])+ylim(-0.0037,0.0013)
ggsave(paste0("../Output/COV_analysis/3Pops_plot1.png"),width = 4.7, height = 3, dpi=300)
    
covs$time<-factor(covs$time, levels=c("cov12","cov23","cov13"))
#xtexts<-c("\u03941991-1996\n ~ \u03941996-2006", "\u03941996-2006\n  ~ \u03942006-2017", "\u03941991-1996\n  ~ \u03942006-2017")
xtexts<-c("\u0394'91-'96\n ~ \u0394'96-'06", "\u0394'96-'06\n  ~ \u0394'06-'17", "\u0394'91-'96\n  ~ \u0394'06-'17")

ggplot(data=covs, aes(x=time, y=cov, color=location))+
        geom_point(size=3, position=position_dodge(width = 0.1,preserve ="total"))+
        #geom_line(data=covs, aes(x=year, y=cov,color=location, group=interaction(location, series)), position=position_dodge(width = 0.1,preserve ="total"))+
        ylab("Covariance")+xlab('')+theme_classic()+
        theme(legend.title = element_blank(), axis.text.x = element_text(size=9))+
        geom_hline(yintercept = 0,color="gray70", size=0.3)+
        geom_errorbar(aes(ymin=cov-ci, ymax=cov+ci), width=.2, size=.2, position=position_dodge(width = 0.1,preserve ="total"))+
        scale_x_discrete(labels=xtexts)+
    scale_color_manual(values=cols[c(2,3,1)])+
    geom_vline(xintercept = c(1.5,2.5), color="gray", size=0.2)+ylim(-0.0038,0.0014)
ggsave(paste0("../Output/COV_analysis/3Pops_plot2.png"),width = 4.57, height = 3, dpi=300)

* Continue to COV_Analysis1 & COV_Analysis2.Rmd

LS0tCnRpdGxlOiAiQ09WIFNjYW4gU2Vuc2l0aXZpdHkgQW5hbHlzaXMgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgICAgdG9jOiB0cnVlIAogICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgIHRoZW1lOiBsdW1lbgogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgICBkZl9wcmludDogcGFnZWQKLS0tCgoqIFRoaXMgbm90ZWJvb2sgc2hvd3MgdGhlIHNlbnNpdGl2aXR5IGFuYWx5c2lzIG9mIHRlbXBvcmFsIGNvdmFyaWFuY2UgYW5hbHlzaXMgZnJvbSBDVlRLUFkuICAKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNvdXJjZSgiQmFzZVNjcmlwdHMuUiIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoc2NhbGVzKQogY29sczwtYygiIzU2YjRlOSIsICIjY2M3OWE3IiwiIzAwOWU3MyIsIiMwMDcyYjIiLCIjZDU1ZTAwIiwiI2U2OWYwMCIsIiNmMGU0NDIiKQpgYGAKCgojIEhvdyBUZW1wb3JhbCBDb3ZhcmlhY25lcyBjaGFuZ2Ugd2l0aCBkZXB0aCBmaWx0ZXJpbmcgIAoKIyMgQ3JlYXRlIFZDRiBmaWxlcyB3aXRoIGRpZmZlcmVudCBtYXhpbXVtIGRlcHRoIGZpbHRlcmluZyAgCiogRmlsdGVyIGJ5IGRlcHRoIGZyb20gdGhlIE1ENzAwMCBWQ0YgZmlsZSB1c2luZyBiY2Z0b29sczoKKiBEZXB0aHMgYXJlIGJhc2VkIG9uIDE0IHBvcHVsYXRpb25zCgpgYGB7YmFzaCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIFVzZSBiY2Z0b29scyB0byBmaWx0ZXIgYnkgTWF4IERlcHRoCmJjZnRvb2xzIGZpbHRlciAtaSAnSU5GTy9EUDwyMDAwJyAzcG9wcy5NRDcwMDBfTlMwLjVfbWFmMDUudmNmLmd6ID4gM3BvcHMuTUQyMDAwLm1hZjA1LnZjZgpiY2Z0b29scyBmaWx0ZXIgLWkgJ0lORk8vRFA8MzAwMCcgM3BvcHMuTUQ3MDAwX05TMC41X21hZjA1LnZjZi5neiA+IDNwb3BzLk1EMzAwMC5tYWYwNS52Y2YKYmNmdG9vbHMgZmlsdGVyIC1pICdJTkZPL0RQPDQwMDAnIDNwb3BzLk1ENzAwMF9OUzAuNV9tYWYwNS52Y2YuZ3ogPiAzcG9wcy5NRDQwMDAubWFmMDUudmNmCmJjZnRvb2xzIGZpbHRlciAtaSAnSU5GTy9EUDw1MDAwJyAzcG9wcy5NRDcwMDBfTlMwLjVfbWFmMDUudmNmLmd6ID4gM3BvcHMuTUQ1MDAwLm1hZjA1LnZjZgpiY2Z0b29scyBmaWx0ZXIgLWkgJ0lORk8vRFA8NjAwMCcgM3BvcHMuTUQ3MDAwX05TMC41X21hZjA1LnZjZi5neiA+IDNwb3BzLk1ENjAwMC5tYWYwNS52Y2YKCmd6aXAgM3BvcHMuTUQyMDAwLm1hZjA1LnZjZgpnemlwIDNwb3BzLk1EMzAwMC5tYWYwNS52Y2YKZ3ppcCAzcG9wcy5NRDQwMDAubWFmMDUudmNmCmd6aXAgM3BvcHMuTUQ1MDAwLm1hZjA1LnZjZgpnemlwIDNwb3BzLk1ENjAwMC5tYWYwNS52Y2YKCmBgYAoKCiMjIFJ1biBDVlRLUFkgb24gZGF0YSB3aXRoIGRpZmZlcmVudCBmaWx0ZXJpbmcgKE1heCBEZXB0aCAyMDAwLTcwMDApCiogQ292YXJpYW5jZXMgZnJvbSBNYXggRGVwdGggMjAwMCB+IDcwMDAgICAKKiAxTSB3aW5kb3cgZm9yIE1EMjAwMC02MDAwLCAxMDBrIGZvciBNRDcwMDAKCiMjIyBNYXggRGVwdGggPSAyMDAwICgxTS13aW5kb3cpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKY292czwtZGF0YS5mcmFtZSgpClZhcmlhbmNlPC1kYXRhLmZyYW1lKCkKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICAjY292YXJpYW5jZSBvdXRwdXQgZmlsZQogICAgY292PC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvTUQyMDAwX21hZjA1X3RlbXBfY292X21hdHJpeF8iLHBvcHNbcF0sIl8xTS5jc3YiKSkKICAgIGNvdjwtY292WywtMV0KICAgICNDSSBmaWxlCiAgICBjaTwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF9tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDBfMU13aW5kb3cuY3N2IikpCiAgICBjaTwtY2lbLC0xXQogICAgICAgIAogICAgI3Jlc2hhcGUgdGhlIG1hdHJpeAogICAgbWF0MTwtY292WzE6MyxdCiAgICBtYXQyPC1jb3ZbNDo2LF0KICAgICAgICAKICAgIGNvdmRmPC1kYXRhLmZyYW1lKCkKICAgIGs9MQogICAgZm9yIChpIGluIDE6bnJvdyhtYXQxKSl7CiAgICAgICAgZm9yIChqIGluIDE6bmNvbChtYXQxKSl7CiAgICAgICAgICAgIGNvdmRmW2ssMV08LW1hdDJbaSxqXQogICAgICAgICAgICBjb3ZkZltrLDJdPC1tYXQxW2ksal0KICAgICAgICAgICAgaz1rKzEKICAgICAgICB9CiAgICB9CiAgICBjb2xuYW1lcyhjb3ZkZik8LWMoImxhYmVsIiwidmFsdWUiKQogICAgY292ZGYkdmFsdWU8LWFzLm51bWVyaWMoY292ZGYkdmFsdWUpCiAgICBjb3ZhcjwtY292ZGZbZ3JlcCgiY292Iixjb3ZkZiRsYWJlbCksXQogICAgdmFyczwtY292ZGZbZ3JlcCgidmFyIixjb3ZkZiRsYWJlbCksXQogICAgICAgIAogICAgI3JlbW92ZSB0aGUgcmVkdW5kYW50IHZhbHVlcwogICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgaWYgKHBvcHNbcF09PSJTUyIpIGNvdmFyPC1jb3ZhcltjKDEsMiw0KSxdCiAgICAgICAgCiAgICAjYXNzaWduIHRoZSBzdGFydGluZyB0aW1lIHBlcmlvZCBhbmQgY292ZXJpbmcgcGVyaW9kIHZhbHVlcwogICAgY292YXIkeWVhcjwtYygxLDIsMikKICAgIGNvdmFyJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgICAgICAKICAgIHZhcnMkeWVhcjwtYygiMTk5MS0xOTk2IiwiMTk5Ni0yMDA2IiwiMjAwNi0yMDE3IikKICAgICN2YXJzJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgICAgICAKICAgICNhc3NpZ24gcG9wdWxhdGlvbiBuYW1lCiAgICBjb3ZhciRsb2NhdGlvbjwtcG9wc1twXQogICAgdmFycyRsb2NhdGlvbjwtcG9wc1twXQogICAgICAgIAogICAgI2F0dGFjaCBjaSBpbmZvCiAgICBjb3ZhciRjaV9sPC1hcy5udW1lcmljKGMoY2lbMSwyXSwgY2lbMSwzXSxjaVsyLDNdKSkKICAgIGNvdmFyJGNpX3U8LWFzLm51bWVyaWMoYyhjaVs0LDJdLCBjaVs0LDNdLGNpWzUsM10pKQogICAgICAgIAogICAgI2NvbWJpbmUgaW4gdG8gb25lIG1hdHJpeAogICAgY292czwtcmJpbmQoY292cywgY292YXIpCiAgICBWYXJpYW5jZTwtcmJpbmQoVmFyaWFuY2UsIHZhcnMpCn0KVmFyaWFuY2UkZGVwdGg8LSJNRDIwMDAiClZhcmlhbmNlczwtVmFyaWFuY2UKeHRleHRzPC1jKCJcdTAzOTQxOTkxLTE5OTZcbiB+IFx1MDM5NDE5OTYtMjAwNiIsICJcbiAgfiBcdTAzOTQyMDA2LTIwMTciKQoKZ2dwbG90KGRhdGE9Y292cywgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9bG9jYXRpb24sIHNoYXBlPXNlcmllcywgZ3JvdXA9aW50ZXJhY3Rpb24obG9jYXRpb24sIHNlcmllcykpKSsKICAgICAgICBnZW9tX3BvaW50KHNpemU9MywgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBnZW9tX2xpbmUoZGF0YT1jb3ZzLCBhZXMoeD15ZWFyLCB5PXZhbHVlLGNvbG9yPWxvY2F0aW9uLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKCJNYXggRGVwdGggPSAyMDAwIikrCiAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSsKICAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLGNvbG9yPSJncmF5NzAiLCBzaXplPTAuMykrCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1jaV9sLCB5bWF4PWNpX3UpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMTYsMTcpLGxhYmVscz1jKCIxOTkxLSIsIjE5OTYtIikpKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDEsMiksIGxhYmVscz14dGV4dHMpKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMywxKV0pCmdnc2F2ZShwYXN0ZTAoIi4uL091dHB1dC9DT1ZfYW5hbHlzaXMvTUQyMDAwX2NvdnMucG5nIiksd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCiAgCmBgYAoKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvTUQyMDAwX2NvdnMucG5nKQoKIyMjIE1EMzAwMC1NRDcwMDAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcG9wczwtYygiUFdTIiwiVEIiLCJTUyIpCm1kczwtYygiTUQzMDAwIiwiTUQ0MDAwIiwiTUQ1MDAwIiwiTUQ2MDAwIiwiTUQ3MDAwIikKeHRleHRzPC1jKCJcdTAzOTQxOTkxLTE5OTZcbiB+IFx1MDM5NDE5OTYtMjAwNiIsICJcbiAgfiBcdTAzOTQyMDA2LTIwMTciKQoKZm9yIChtIGluIDE6IGxlbmd0aChtZHMpKXsKICAgIGNvdnM8LWRhdGEuZnJhbWUoKQogICAgVmFyaWFuY2U8LWRhdGEuZnJhbWUoKQogICAgaWYobT09NSl7CiAgICAgICAgZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICAgICAgICAgIGNvdjwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzLyIsbWRzW21dLCJfbWFmMDVfdGVtcF9jb3ZfbWF0cml4XyIscG9wc1twXSwiLmNzdiIpKQogICAgICAgICAgICBjb3Y8LWNvdlssLTFdCiAgICAgICAgICAgIGNpPC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvIixtZHNbbV0sIl9tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDAuY3N2IikpCiAgICAgICAgICAgIGNpPC1jaVssLTFdCiAgICAgICAgCiAgICAgICAgICAgIG1hdDE8LWNvdlsxOjMsXQogICAgICAgICAgICBtYXQyPC1jb3ZbNDo2LF0KICAgICAgICAgICAgCiAgICAgICAgICAgIGNvdmRmPC1kYXRhLmZyYW1lKCkKICAgICAgICAgICAgaz0xCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3cobWF0MSkpewogICAgICAgICAgICAgICAgZm9yIChqIGluIDE6bmNvbChtYXQxKSl7CiAgICAgICAgICAgICAgICAgICAgY292ZGZbaywxXTwtbWF0MltpLGpdCiAgICAgICAgICAgICAgICAgICAgY292ZGZbaywyXTwtbWF0MVtpLGpdCiAgICAgICAgICAgICAgICAgICAgaz1rKzEKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29sbmFtZXMoY292ZGYpPC1jKCJsYWJlbCIsInZhbHVlIikKICAgICAgICBjb3ZkZiR2YWx1ZTwtYXMubnVtZXJpYyhjb3ZkZiR2YWx1ZSkKICAgICAgICBjb3ZhcjwtY292ZGZbZ3JlcCgiY292Iixjb3ZkZiRsYWJlbCksXQogICAgICAgIHZhcnM8LWNvdmRmW2dyZXAoInZhciIsY292ZGYkbGFiZWwpLF0KICAgICAgICAgICAgCiAgICAgICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgICAgIGlmIChwb3BzW3BdPT0iU1MiKSBjb3ZhcjwtY292YXJbYygxLDIsNCksXQogICAgICAgICAgICAKICAgICAgICAjYXNzaWduIHRoZSBzdGFydGluZyB0aW1lIHBlcmlvZCBhbmQgY292ZXJpbmcgcGVyaW9kIHZhbHVlcwogICAgICAgIGNvdmFyJHllYXI8LWMoMSwyLDIpCiAgICAgICAgY292YXIkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgICAgICAgICAKICAgICAgICB2YXJzJHllYXI8LWMoIjE5OTEtMTk5NiIsIjE5OTYtMjAwNiIsIjIwMDYtMjAxNyIpCiAgICAgICAgICAgIAogICAgICAgICNhc3NpZ24gcG9wdWxhdGlvbiBuYW1lCiAgICAgICAgY292YXIkbG9jYXRpb248LXBvcHNbcF0KICAgICAgICB2YXJzJGxvY2F0aW9uPC1wb3BzW3BdCiAgICAgICAgICAgIAogICAgICAgICNhdHRhY2ggY2kgaW5mbwogICAgICAgIGNvdmFyJGNpX2w8LWFzLm51bWVyaWMoYyhjaVsxLDJdLCBjaVsxLDNdLGNpWzIsM10pKQogICAgICAgIGNvdmFyJGNpX3U8LWFzLm51bWVyaWMoYyhjaVs0LDJdLCBjaVs0LDNdLGNpWzUsM10pKQogICAgICAgICAgICAKICAgICAgICAjY29tYmluZSBpbiB0byBvbmUgbWF0cml4CiAgICAgICAgY292czwtcmJpbmQoY292cywgY292YXIpCiAgICAgICAgVmFyaWFuY2U8LXJiaW5kKFZhcmlhbmNlLCB2YXJzKQogICAgICAgIH0KICAgIH0KICAgIGVsc2V7CiAgICAgICAgZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICAgICAgY292PC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvIixtZHNbbV0sIl9tYWYwNV90ZW1wX2Nvdl9tYXRyaXhfIixwb3BzW3BdLCJfMU0uY3N2IikpCiAgICAgICAgY292PC1jb3ZbLC0xXQogICAgICAgIGNpPC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvIixtZHNbbV0sIl9tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDBfMU13aW5kb3cuY3N2IikpCiAgICAgICAgY2k8LWNpWywtMV0KICAgICAgICAKICAgICAgICBtYXQxPC1jb3ZbMTozLF0KICAgICAgICBtYXQyPC1jb3ZbNDo2LF0KICAgICAgICAKICAgICAgICBjb3ZkZjwtZGF0YS5mcmFtZSgpCiAgICAgICAgaz0xCiAgICAgICAgZm9yIChpIGluIDE6bnJvdyhtYXQxKSl7CiAgICAgICAgICAgIGZvciAoaiBpbiAxOm5jb2wobWF0MSkpewogICAgICAgICAgICAgICAgY292ZGZbaywxXTwtbWF0MltpLGpdCiAgICAgICAgICAgICAgICBjb3ZkZltrLDJdPC1tYXQxW2ksal0KICAgICAgICAgICAgICAgIGs9aysxCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgY29sbmFtZXMoY292ZGYpPC1jKCJsYWJlbCIsInZhbHVlIikKICAgICAgICBjb3ZkZiR2YWx1ZTwtYXMubnVtZXJpYyhjb3ZkZiR2YWx1ZSkKICAgICAgICBjb3ZhcjwtY292ZGZbZ3JlcCgiY292Iixjb3ZkZiRsYWJlbCksXQogICAgICAgIHZhcnM8LWNvdmRmW2dyZXAoInZhciIsY292ZGYkbGFiZWwpLF0KICAgICAgICAgICAgCiAgICAgICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgICAgIGlmIChwb3BzW3BdPT0iU1MiKSBjb3ZhcjwtY292YXJbYygxLDIsNCksXQogICAgICAgICAgICAKICAgICAgICAjYXNzaWduIHRoZSBzdGFydGluZyB0aW1lIHBlcmlvZCBhbmQgY292ZXJpbmcgcGVyaW9kIHZhbHVlcwogICAgICAgIGNvdmFyJHllYXI8LWMoMSwyLDIpCiAgICAgICAgY292YXIkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgICAgICAgICAKICAgICAgICB2YXJzJHllYXI8LWMoIjE5OTEtMTk5NiIsIjE5OTYtMjAwNiIsIjIwMDYtMjAxNyIpCiAgICAgICAgICAgIAogICAgICAgICNhc3NpZ24gcG9wdWxhdGlvbiBuYW1lCiAgICAgICAgY292YXIkbG9jYXRpb248LXBvcHNbcF0KICAgICAgICB2YXJzJGxvY2F0aW9uPC1wb3BzW3BdCiAgICAgICAgICAgIAogICAgICAgICNhdHRhY2ggY2kgaW5mbwogICAgICAgIGNvdmFyJGNpX2w8LWFzLm51bWVyaWMoYyhjaVsxLDJdLCBjaVsxLDNdLGNpWzIsM10pKQogICAgICAgIGNvdmFyJGNpX3U8LWFzLm51bWVyaWMoYyhjaVs0LDJdLCBjaVs0LDNdLGNpWzUsM10pKQogICAgICAgICAgICAKICAgICAgICAjY29tYmluZSBpbiB0byBvbmUgbWF0cml4CiAgICAgICAgY292czwtcmJpbmQoY292cywgY292YXIpCiAgICAgICAgVmFyaWFuY2U8LXJiaW5kKFZhcmlhbmNlLCB2YXJzKQogICAgICAgIH0KICAgIH0KICAgICAgICAKICAgIFZhcmlhbmNlJGRlcHRoPC1tZHNbbV0KICAgIFZhcmlhbmNlczwtcmJpbmQoVmFyaWFuY2VzLFZhcmlhbmNlKQogICAgZ2dwbG90KGRhdGE9Y292cywgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9bG9jYXRpb24sIHNoYXBlPXNlcmllcywgZ3JvdXA9aW50ZXJhY3Rpb24obG9jYXRpb24sIHNlcmllcykpKSsKICAgICAgICBnZW9tX3BvaW50KHNpemU9MywgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBnZW9tX2xpbmUoZGF0YT1jb3ZzLCBhZXMoeD15ZWFyLCB5PXZhbHVlLGNvbG9yPWxvY2F0aW9uLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKG1kc1ttXSkrCiAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSsKICAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLGNvbG9yPSJncmF5NzAiLCBzaXplPTAuMykrCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1jaV9sLCB5bWF4PWNpX3UpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMTYsMTcpLGxhYmVscz1jKCIxOTkxLSIsIjE5OTYtIikpKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDEsMiksIGxhYmVscz14dGV4dHMpKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMywxKV0pCiAgICBnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WX2FuYWx5c2lzLyIsbWRzW21dLCJfY292cy5wbmciKSx3aWR0aCA9IDQuNywgaGVpZ2h0ID0gMywgZHBpPTMwMCkgICAgCn0KClZhcmlhbmNlc19vcmc8LVZhcmlhbmNlcwpgYGAKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL01EMzAwMF9jb3ZzLnBuZykKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL01ENDAwMF9jb3ZzLnBuZykKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL01ENTAwMF9jb3ZzLnBuZykKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL01ENjAwMF9jb3ZzLnBuZykKCgojIyBQbG90IFZhcmlhbmNlcwpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzZXFjb2xzPC1zZXF1ZW50aWFsX2hjbCg2LCBwYWxldHRlPSJSZWQtQmx1ZSIpCiNyZXZlcnNlIHRoZSBvcmRlcgpzZXFjb2xzPC1yZXYoc2VxY29scykKY29sbmFtZXMoVmFyaWFuY2VzKVsyXTwtIlZhcmlhbmNlIgpnZ3Bsb3QoVmFyaWFuY2VzLCBhZXMoeD15ZWFyLCB5PVZhcmlhbmNlLCBmaWxsPWRlcHRoKSkrCiAgICBmYWNldF93cmFwKH5sb2NhdGlvbiwgbmNvbD0xKSsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC44KSkrCiAgICB0aGVtZV9idygpK2dlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yPSJncmF5MzAiLCBzaXplPTAuMykrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9c2VxY29scywgbmFtZT0iTWF4IGRlcHRoIikKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WX2FuYWx5c2lzL3ZhcmlhbmNlc19ieU1heERlcHRoRmlsdGVyLnBuZyIsIHdpZHRoID0gNywgaGVpZ2h0PTYsIGRwaT0zMDApCgpgYGAKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL3ZhcmlhbmNlc19ieU1heERlcHRoRmlsdGVyLnBuZykKCiMjIERpYWdub3N0aWMgcGxvdHMgZnJvbSBDVlRLUFkKCiMjIyBNRDcwMDAgb3JpZ2luYWwgZGlhZ25vc3RpYyBwbG90cyAoY29ycmVjdGlvbiB2cy4gbm9uZSkgIAohW10oLi4vY3Z0a19hbmFseXNpcy9NRDcwMDBfY292X2NvcnJlY3Rpb24ucG5nKQoKCiMjIyBNRDIwMDAgIAohW10oLi4vY3Z0a19hbmFseXNpcy9NRDIwMDBfY292X2NvcnJlY3Rpb24ucG5nKQoKIyMjIE1EMzAwMCAgCiFbXSguLi9jdnRrX2FuYWx5c2lzL01EMzAwMF9jb3ZfY29ycmVjdGlvbi5wbmcpCgojIyBNRDQwMDAKIVtdKC4uL2N2dGtfYW5hbHlzaXMvTUQ0MDAwX2Nvdl9jb3JyZWN0aW9uLnBuZykgIAoKCjxicj4KPGJyPgo8YnI+CgojIENyZWF0ZSBuZXcgVkNGIGZpbGVzIHdpdGggbmV3IGZpbHRlcmluZyAoTUQzMDAwICYgTUQyMDAwKQoKCiMjIENyZWF0ZSBxdWFsaXR5IGZpbHRlcmVkIHNucHMgZm9yIDMgcG9wcyBhdCBGQVJNLCBhbmQgZmlsdGVyIHRvIERQPDIwMDAgbG9jYWxseSAoRkFSTSBkb2VzIG5vdCBoYXZlIHRoZSBsYXRlc3QgYmNmdG9vbHMpIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZm9yIChpIGluIG4pewogICAgc2luayhwYXN0ZTAoIi4uL0RhdGEvU2x1cm1zY3JpcHRzLzAuZmlsdGVyX3Jhd18iLGksIi5zaCIpKQogICAgY2F0KCIjIS9iaW4vYmFzaCAtbFxuIikKICAgIGNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1qb2ItbmFtZT1maWx0ZXIiLGksIiBcbiIpKQogICAgY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW1lbT0xNkcgXG4iKSkgCiAgICBjYXQocGFzdGUwKCIjU0JBVENIIC0tbnRhc2tzPTggXG4iKSkgCiAgICBjYXQocGFzdGUwKCIjU0JBVENIIC1lIGZpbHRlciIsaSwiLmVyciAgXG4iKSkKICAgIGNhdChwYXN0ZTAoIiNTQkFUQ0ggLS10aW1lPTE0NDowMDowMCAgXG4iKSkKICAgIGNhdChwYXN0ZTAoIiNTQkFUQ0ggLXAgaGlnaCAgXG4iKSkKICAgIGNhdCgiXG5cbiIpCiAgICBjYXQoJ21vZHVsZSBsb2FkIHNhbXRvb2xzIFxuJykgCiAgICBjYXQoJ21vZHVsZSBsb2FkIGJjZnRvb2xzIFxuXG4nKSAKICAgIAogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgdmlldyAtUyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvcG9wdWxhdGlvbi90aW1lc2VyaWVzLnR4dCAtbTIgLU0yIC12IHNucHMgL2hvbWUvamFtY2dpcnIvcGgvZGF0YS9jb21iaW5lX2d2Y2ZzL3Jhd192YXJpYW50c19jaHIiLGksIl8xLnZjZiB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ01RPjMwICYmIFFVQUw+MjAnIC1vIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9WQ0YvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzEudmNmLmd6ICBcbiIpKQogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgdmlldyAtUyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvcG9wdWxhdGlvbi90aW1lc2VyaWVzLnR4dCAtbTIgLU0yIC12IHNucHMgL2hvbWUvamFtY2dpcnIvcGgvZGF0YS9jb21iaW5lX2d2Y2ZzL3Jhd192YXJpYW50c19jaHIiLGksIl8yLnZjZiB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ01RPjMwICYmIFFVQUw+MjAnIC1vIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9WQ0YvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzIudmNmLmd6ICBcbiIpKQogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgaW5kZXggL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL1ZDRi9xdWFsX2ZpbHRlcmVkX3NucHNfY2hyIixpLCJfMS52Y2YuZ3pcbiIpKQogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgaW5kZXggL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL1ZDRi9xdWFsX2ZpbHRlcmVkX3NucHNfY2hyIixpLCJfMi52Y2YuZ3ogXG5cbiIpKSAKICAgIAogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgdmlldyAtUyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvcG9wdWxhdGlvbi90aW1lc2VyaWVzLnR4dCAtbTIgLU0yIC12IHNucHMgL2hvbWUvamFtY2dpcnIvcGgvZGF0YS9jb21iaW5lX2d2Y2ZzL3Jhd192YXJpYW50c19jaHIiLGkrMSwiXzEudmNmIHwgYmNmdG9vbHMgZmlsdGVyIC1PeiAtaSAnTVE+MzAgJiYgUVVBTD4yMCcgLW8gL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL1ZDRi9xdWFsX2ZpbHRlcmVkX3NucHNfY2hyIixpKzEsIl8xLnZjZi5neiAgXG4iKSkKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIHZpZXcgLVMgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL3BvcHVsYXRpb24vdGltZXNlcmllcy50eHQgLW0yIC1NMiAtdiBzbnBzIC9ob21lL2phbWNnaXJyL3BoL2RhdGEvY29tYmluZV9ndmNmcy9yYXdfdmFyaWFudHNfY2hyIixpKzEsIl8yLnZjZiB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ01RPjMwICYmIFFVQUw+MjAnIC1vIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9WQ0YvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSsxLCJfMi52Y2YuZ3ogIFxuIikpCiAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBpbmRleCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvVkNGL3F1YWxfZmlsdGVyZWRfc25wc19jaHIiLGkrMSwiXzEudmNmLmd6XG4iKSkKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9WQ0YvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSsxLCJfMi52Y2YuZ3ogXG5cbiIpKSAKc2luayhOVUxMKQp9ICAKCgojIGNyZWF0ZSBiYXNoIHNjcmlwdHMgdG8gcnVuIGxvY2FsbHkKCnNpbmsocGFzdGUwKCIuLi9EYXRhL1NsdXJtc2NyaXB0cy8xLmZpbHRlcl9ieURlcHRoLnNoIikpCmNhdCgiIyEvYmluL2Jhc2ggXG4iKQpmb3IgKGkgaW4gMToyNil7CiAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBhbm5vdGF0ZSAteCBJTkZPL0RQIC9Vc2Vycy9rYWhvdGlzdGhhbW1lci9Qcm9qZWN0cy9QYWNIZXJyaW5nL0RhdGEvbmV3X3ZjZi9NRDMwMDAvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzEudmNmLmd6IHxiY2Z0b29scyArZmlsbC10YWdzIC0tIC10ICdJTkZPL0RQPXN1bShEUCknIHwgYmNmdG9vbHMgZmlsdGVyIC1PeiAtaSAnSU5GTy9EUD40NzEgJiYgSU5GTy9EUDwzMDAwJyAtbyAvVXNlcnMva2Fob3Rpc3RoYW1tZXIvUHJvamVjdHMvUGFjSGVycmluZy9EYXRhL25ld192Y2YvTUQzMDAwL2ZpbHRlcmVkX3NucHNfTUQzMDAwX2NociIsaSwiXzEudmNmLmd6ICAgXG4iKSkKICAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBhbm5vdGF0ZSAteCBJTkZPL0RQIC9Vc2Vycy9rYWhvdGlzdGhhbW1lci9Qcm9qZWN0cy9QYWNIZXJyaW5nL0RhdGEvbmV3X3ZjZi9NRDMwMDAvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzIudmNmLmd6IHwgYmNmdG9vbHMgK2ZpbGwtdGFncyAtLSAtdCAnSU5GTy9EUD1zdW0oRFApJyB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ0lORk8vRFA+NDcxICYmIElORk8vRFA8MzAwMCcgLW8gL1VzZXJzL2thaG90aXN0aGFtbWVyL1Byb2plY3RzL1BhY0hlcnJpbmcvRGF0YS9uZXdfdmNmL01EMzAwMC9maWx0ZXJlZF9zbnBzX01EMzAwMF9jaHIiLGksIl8yLnZjZi5neiAgIFxuIikpCiAgICAKfQpzaW5rKE5VTEwpCgoKc2luayhwYXN0ZTAoIi4uL0RhdGEvU2x1cm1zY3JpcHRzLzEuZmlsdGVyX2J5RGVwdGgyLnNoIikpCmNhdCgiIyEvYmluL2Jhc2ggXG4iKQpmb3IgKGkgaW4gMToyNil7CiAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBhbm5vdGF0ZSAteCBJTkZPL0RQIC9Vc2Vycy9rYWhvdGlzdGhhbW1lci9Qcm9qZWN0cy9QYWNIZXJyaW5nL0RhdGEvbmV3X3ZjZi9NRDIwMDAvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzEudmNmLmd6IHxiY2Z0b29scyArZmlsbC10YWdzIC0tIC10ICdJTkZPL0RQPXN1bShEUCknIHwgYmNmdG9vbHMgZmlsdGVyIC1PeiAtaSAnSU5GTy9EUD40NzEgJiYgSU5GTy9EUDwyMDAwJyAtbyAvVXNlcnMva2Fob3Rpc3RoYW1tZXIvUHJvamVjdHMvUGFjSGVycmluZy9EYXRhL25ld192Y2YvTUQyMDAwL2ZpbHRlcmVkX3NucHNfTUQyMDAwX2NociIsaSwiXzEudmNmLmd6ICAgXG4iKSkKICAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBhbm5vdGF0ZSAteCBJTkZPL0RQIC9Vc2Vycy9rYWhvdGlzdGhhbW1lci9Qcm9qZWN0cy9QYWNIZXJyaW5nL0RhdGEvbmV3X3ZjZi9NRDIwMDAvcXVhbF9maWx0ZXJlZF9zbnBzX2NociIsaSwiXzIudmNmLmd6IHwgYmNmdG9vbHMgK2ZpbGwtdGFncyAtLSAtdCAnSU5GTy9EUD1zdW0oRFApJyB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ0lORk8vRFA+NDcxICYmIElORk8vRFA8MjAwMCcgLW8gL1VzZXJzL2thaG90aXN0aGFtbWVyL1Byb2plY3RzL1BhY0hlcnJpbmcvRGF0YS9uZXdfdmNmL01EMjAwMC9maWx0ZXJlZF9zbnBzX01EMjAwMF9jaHIiLGksIl8yLnZjZi5neiAgIFxuIikpCiAgICAKfQpzaW5rKE5VTEwpCiAgICAgICAgICAgICAgIApgYGAKCiMjIE1lcmdlIGFsbCB2Y2ZzCiAgCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNpbmsocGFzdGUwKCIuLi9EYXRhL1NsdXJtc2NyaXB0cy8yLk1lcmdlX01EMzAwMFZDRnMuc2giKSkKY2F0KCIjIS9iaW4vYmFzaCAtbFxuIikKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLWpvYi1uYW1lPW1lcmdlVkNGcyBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tbWVtPTE2RyBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW50YXNrcz04IFxuIikpIApjYXQocGFzdGUwKCIjU0JBVENIIC0tbm9kZXM9NCBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtZSBtZXJnZVZDRnMuZXJyICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tdGltZT03MjowMDowMCAgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtcCBoaWdoICBcbiIpKQpjYXQoIlxuXG4iKQoKY2F0KCdtb2R1bGUgbG9hZCBiY2Z0b29scyBcblxuJykgCmZvciAoaSBpbiAxOjI2KXsKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9maWx0ZXJlZF9zbnBzX01EMzAwMF9jaHIiLGksIl8xLnZjZi5neiBcbiIpKQogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgaW5kZXggL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL2ZpbHRlcmVkX3NucHNfTUQzMDAwX2NociIsaSwiXzIudmNmLmd6IFxuIikpCn0KY2F0KCJcbiIpCmNhdCgiYmNmdG9vbHMgY29uY2F0IC1vIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvbWVyZ2VkX2ZpbHRlcmVkX3NucHNfTUQzMDAwLmJjZiAtTyBiIC0tdGhyZWFkcyAyNCAiKSAKZm9yIChpIGluIDE6MjYpewogICAgY2F0KHBhc3RlMCgiL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMzAwMC9maWx0ZXJlZF9zbnBzX01EMzAwMF9jaHIiLGksIl8xLnZjZi5neiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQzMDAwL2ZpbHRlcmVkX3NucHNfTUQzMDAwX2NociIsaSwiXzIudmNmLmd6ICIpKQp9CmNhdCgiXG4iKQpjYXQoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvbWVyZ2VkX2ZpbHRlcmVkX3NucHNfTUQzMDAwLmJjZiBcbiIpCnNpbmsoTlVMTCkKCgpzaW5rKHBhc3RlMCgiLi4vRGF0YS9TbHVybXNjcmlwdHMvMi5NZXJnZV9NRDIwMDBWQ0ZzLnNoIikpCmNhdCgiIyEvYmluL2Jhc2ggLWxcbiIpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1qb2ItbmFtZT1tZXJnZVZDRnMgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW1lbT0xNkcgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1udGFza3M9OCBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW5vZGVzPTQgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLWUgbWVyZ2VWQ0ZzLmVyciAgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLXRpbWU9NzI6MDA6MDAgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLXAgaGlnaCAgXG4iKSkKY2F0KCJcblxuIikKCmNhdCgnbW9kdWxlIGxvYWQgYmNmdG9vbHMgXG5cbicpIApmb3IgKGkgaW4gMToyNil7CiAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBpbmRleCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvZmlsdGVyZWRfc25wc19NRDIwMDBfY2hyIixpLCJfMS52Y2YuZ3ogXG4iKSkKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9maWx0ZXJlZF9zbnBzX01EMjAwMF9jaHIiLGksIl8yLnZjZi5neiBcbiIpKQp9CmNhdCgiXG4iKQpjYXQoImJjZnRvb2xzIGNvbmNhdCAtbyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwL21lcmdlZF9maWx0ZXJlZF9zbnBzX01EMjAwMC5iY2YgLU8gYiAtLXRocmVhZHMgMjQgIikgCmZvciAoaSBpbiAxOjI2KXsKICAgIGNhdChwYXN0ZTAoIi9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvZmlsdGVyZWRfc25wc19NRDIwMDBfY2hyIixpLCJfMS52Y2YuZ3ogL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC9maWx0ZXJlZF9zbnBzX01EMjAwMF9jaHIiLGksIl8yLnZjZi5neiAiKSkKfQpjYXQoIlxuIikKY2F0KCJiY2Z0b29scyBpbmRleCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwL21lcmdlZF9maWx0ZXJlZF9zbnBzX01EMjAwMC5iY2YgXG4iKQpzaW5rKE5VTEwpCgpgYGAKCiMjIFN1YnNldCB2Y2YgaW50byAxMSBwb3B1bGF0aW9ucyAoZ3JvdXBlZCBieSB1bmlxdWUobG9jYXRpb246eWVhcikpIGFuZCBmaWx0ZXIgZm9yIDUwJSBnZW5vdHlwaW5nIHJhdGUKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBvcF9pbmZvPC1yZWFkLmNzdigiLi4vRGF0YS9TYW1wbGVfbWV0YWRhdGFfODkycG9wcy5jc3YiKQpwb3BzPC11bmlxdWUocG9wX2luZm8kUG9wdWxhdGlvbi5ZZWFyKSAKcG9wczwtcG9wc1tncmVwKCJQV1N8U1N8VEIiLCBwb3BzKV0KcG9wc2l6ZTwtZGF0YS5mcmFtZSh0YWJsZShwb3BfaW5mbyRQb3B1bGF0aW9uLlllYXIpKQoKIyBNRDMwMDAKc2luayhwYXN0ZTAoIi4uL0RhdGEvU2x1cm1zY3JpcHRzLzMuU3Vic2V0VkNGc19maWx0ZXJOUzAuNV9NRDMwMDAuc2giKSkKY2F0KCIjIS9iaW4vYmFzaCAtbFxuIikKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLWpvYi1uYW1lPXN1YnNldCBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tbWVtPTE2RyBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW50YXNrcz04IFxuIikpIApjYXQocGFzdGUwKCIjU0JBVENIIC0tbm9kZXM9NCBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtZSBzdWJzZXRWQ0ZzLmVyciAgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLXRpbWU9NzI6MDA6MDAgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLXAgaGlnaCAgXG4iKSkKY2F0KCJcblxuIikKY2F0KCdtb2R1bGUgbG9hZCBiY2Z0b29scyBcblxuJykgCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBuPC1wb3BzaXplJEZyZXFbcG9wc2l6ZSRWYXIxPT1wb3BzW2ldXS8yCgogICAgY2F0KHBhc3RlMCgiYmNmdG9vbHMgdmlldyAtUyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvcG9wdWxhdGlvbi8iLCBwb3BzW2ldLCAiLnR4dCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQzMDAwL21lcmdlZF9maWx0ZXJlZF9zbnBzX01EMzAwMC5iY2YgfCBiY2Z0b29scyArZmlsbC10YWdzIC0tIC10IGFsbCwnTlMnIHwgYmNmdG9vbHMgZmlsdGVyIC1PeiAtaSAnTlM+IixuLCInID4gIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvIixwb3BzW2ldLCJfZmlsdGVyZWRfTUQzMDAwLnZjZi5neiBcbiIpICkKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvIixwb3BzW2ldLCJfZmlsdGVyZWRfTUQzMDAwLnZjZi5neiBcbiIpKQp9CnNpbmsoTlVMTCkKCiMgTUQyMDAwCnNpbmsocGFzdGUwKCIuLi9EYXRhL1NsdXJtc2NyaXB0cy8zLlN1YnNldFZDRnNfZmlsdGVyTlMwLjVfTUQyMDAwLnNoIikpCmNhdCgiIyEvYmluL2Jhc2ggLWxcbiIpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1qb2ItbmFtZT1zdWJzZXQgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW1lbT0xNkcgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1udGFza3M9OCBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW5vZGVzPTQgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLWUgc3Vic2V0VkNGcy5lcnIgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS10aW1lPTcyOjAwOjAwICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC1wIGhpZ2ggIFxuIikpCmNhdCgiXG5cbiIpCmNhdCgnbW9kdWxlIGxvYWQgYmNmdG9vbHMgXG5cbicpIApmb3IgKGkgaW4gMTpsZW5ndGgocG9wcykpewogICAgbjwtcG9wc2l6ZSRGcmVxW3BvcHNpemUkVmFyMT09cG9wc1tpXV0vMgoKICAgIGNhdChwYXN0ZTAoImJjZnRvb2xzIHZpZXcgLVMgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL3BvcHVsYXRpb24vIiwgcG9wc1tpXSwgIi50eHQgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC9tZXJnZWRfZmlsdGVyZWRfc25wc19NRDIwMDAuYmNmIHwgYmNmdG9vbHMgK2ZpbGwtdGFncyAtLSAtdCBhbGwsJ05TJyB8IGJjZnRvb2xzIGZpbHRlciAtT3ogLWkgJ05TPiIsbiwiJyA+ICAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwLyIscG9wc1tpXSwiX2ZpbHRlcmVkX01EMjAwMC52Y2YuZ3ogXG4iKSApCiAgICBjYXQocGFzdGUwKCJiY2Z0b29scyBpbmRleCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwLyIscG9wc1tpXSwiX2ZpbHRlcmVkX01EMjAwMC52Y2YuZ3ogXG4iKSkKfQpzaW5rKE5VTEwpCmBgYAoKCiMjIEZpbmQgaW50ZXJzZWN0aW5nIGxvY2kgCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojTUQzMDAwCnNpbmsocGFzdGUwKCIuLi9EYXRhL1NsdXJtc2NyaXB0cy80LklzZWNfTUQzMDAwXzNwb3BzLnNoIikpCmNhdCgiIyEvYmluL2Jhc2ggLWxcbiIpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1qb2ItbmFtZT1pc2VjM3BvcHMyIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1tZW09MTZHIFxuIikpIApjYXQocGFzdGUwKCIjU0JBVENIIC0tbnRhc2tzPTggXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLWUgaXNlYzNwb3BzMi5lcnIgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS10aW1lPTcyOjAwOjAwICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC1wIGhpZ2ggIFxuIikpCmNhdCgiXG5cbiIpCgpjYXQoJ21vZHVsZSBsb2FkIGJjZnRvb2xzIFxuXG4nKSAKCmNhdChwYXN0ZTAoImJjZnRvb2xzIGlzZWMgLW49MTEgLXAgaXNlYzNwb3BzX01EMzAwMCAtLXRocmVhZHMgMjQgIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvUFdTMTdfZmlsdGVyZWRfTUQzMDAwLnZjZi5neiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQzMDAwL1BXUzkxX2ZpbHRlcmVkX01EMzAwMC52Y2YuZ3ogL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMzAwMC9QV1M5Nl9maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvU1MwNl9maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvU1MxN19maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvU1M5Nl9maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvVEIwNl9maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvVEIxN19maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvVEI5MV9maWx0ZXJlZF9NRDMwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvVEI5Nl9maWx0ZXJlZF9NRDMwMDAudmNmLmd6ICBcbiIpKQpzaW5rKE5VTEwpCgoKI01EMjAwMApzaW5rKHBhc3RlMCgiLi4vRGF0YS9TbHVybXNjcmlwdHMvSXNlY19NRDIwMDBfM3BvcHMuc2giKSkKY2F0KCIjIS9iaW4vYmFzaCAtbFxuIikKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLWpvYi1uYW1lPWlzZWMzcG9wcyBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tbWVtPTE2RyBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW50YXNrcz04IFxuIikpIApjYXQocGFzdGUwKCIjU0JBVENIIC1lIGlzZWMzcG9wcy5lcnIgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS10aW1lPTcyOjAwOjAwICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC1wIGhpZ2ggIFxuIikpCmNhdCgiXG5cbiIpCgpjYXQoJ21vZHVsZSBsb2FkIGJjZnRvb2xzIFxuXG4nKSAKCmNhdChwYXN0ZTAoImJjZnRvb2xzIGlzZWMgLW49MTEgLXAgaXNlYzNwb3BzX01EMjAwMCAtLXRocmVhZHMgMjQgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC9QV1MwN19maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvUFdTMTdfZmlsdGVyZWRfTUQyMDAwLnZjZi5neiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwL1BXUzkxX2ZpbHRlcmVkX01EMjAwMC52Y2YuZ3ogL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC9QV1M5Nl9maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvU1MwNl9maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvU1MxN19maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvU1M5Nl9maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvVEIwNl9maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvVEIxN19maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvVEI5MV9maWx0ZXJlZF9NRDIwMDAudmNmLmd6IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvVEI5Nl9maWx0ZXJlZF9NRDIwMDAudmNmLmd6ICBcbiIpKQogICAgCnNpbmsoTlVMTCkKYGBgCgojIyBGaWx0ZXIgdG8gdGhlIGludGVyc2VjdGluZyBsb2NpIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI01EMzAwMApzaW5rKHBhc3RlMCgiLi4vRGF0YS9TbHVybXNjcmlwdHMvNS5GaWx0ZXJNRDMwMDBfM3BvcHMuc2giKSkKY2F0KCIjIS9iaW4vYmFzaCAtbFxuIikKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLWpvYi1uYW1lPTNrZmlsIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1tZW09MTZHIFxuIikpIApjYXQocGFzdGUwKCIjU0JBVENIIC0tbnRhc2tzPTggXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1ub2Rlcz00IFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLWUgM2tmaWwuZXJyICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tdGltZT0xNDQ6MDA6MDAgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLXAgaGlnaCAgXG4iKSkKY2F0KCJcblxuIikKCmNhdCgnbW9kdWxlIGxvYWQgYmNmdG9vbHMgXG5cbicpIApjYXQoImJjZnRvb2xzIHZpZXcgLVMgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL3BvcHVsYXRpb24vdGltZXNlcmllcy50eHQgLVIgL2hvbWUva3Rpc3QvaXNlYzNwb3BzX01EMzAwMC9zaXRlcy50eHQgLU96IC0tdGhyZWFkcyAyNCAgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMzAwMC9tZXJnZWRfZmlsdGVyZWRfc25wc19NRDMwMDAuYmNmID4gIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDMwMDAvM3BvcHNfTUQzMDAwX05TMC41LnZjZi5neiBcbiIpCgpjYXQoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi8zcG9wc19NRDMwMDBfTlMwLjUudmNmLmd6IFxuIikKCmNhdCgiYmNmdG9vbHMgZmlsdGVyIC1PeiAtLXRocmVhZHMgMjQgLWkgJ0lORk8vQUY+MC4wNScgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmLzNwb3BzX01EMzAwMF9OUzAuNS52Y2YuZ3ogLW8gL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC8zcG9wc19NRDMwMDBfbWFmMDUudmNmLmd6IFxuIikKCmNhdCgiYmNmdG9vbHMgaW5kZXggL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMzAwMC8zcG9wc19NRDMwMDBfbWFmMDUudmNmLmd6IFxuIikKc2luayhOVUxMKQoKI01EMjAwMApzaW5rKHBhc3RlMCgiLi4vRGF0YS9TbHVybXNjcmlwdHMvRmlsdGVyTUQyMDAwXzNwb3BzMi5zaCIpKQpjYXQoIiMhL2Jpbi9iYXNoIC1sXG4iKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tam9iLW5hbWU9MmtGaWwgXG4iKSkKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW1lbT0xNkcgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLS1udGFza3M9OCBcbiIpKSAKY2F0KHBhc3RlMCgiI1NCQVRDSCAtLW5vZGVzPTQgXG4iKSkgCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLWUgMmtGaWwuZXJyICBcbiIpKQpjYXQocGFzdGUwKCIjU0JBVENIIC0tdGltZT0xNDQ6MDA6MDAgIFxuIikpCmNhdChwYXN0ZTAoIiNTQkFUQ0ggLXAgaGlnaCAgXG4iKSkKY2F0KCJcblxuIikKCmNhdCgnbW9kdWxlIGxvYWQgYmNmdG9vbHMgXG5cbicpIApjYXQoImJjZnRvb2xzIHZpZXcgLU96IC1TIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9wb3B1bGF0aW9uL3RpbWVzZXJpZXMudHh0IC0tdGhyZWFkcyAyNCAgLVIgL2hvbWUva3Rpc3QvaXNlYzNwb3BzX01EMjAwMC9zaXRlcy50eHQgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC9tZXJnZWRfZmlsdGVyZWRfc25wc19NRDIwMDAuYmNmICA+IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvM3BvcHNfTUQyMDAwX05TMC41LnZjZi5neiBcbiIpCgpjYXQoImJjZnRvb2xzIGluZGV4IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDIwMDAvM3BvcHNfTUQyMDAwX05TMC41LnZjZi5neiAgXG4iKQoKY2F0KCJiY2Z0b29scyBmaWx0ZXIgLU96IC0tdGhyZWFkcyAyNCAtaSAnSU5GTy9BRj4wLjA1JyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwLzNwb3BzX01EMjAwMF9OUzAuNS52Y2YuZ3ogLW8gL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01EMjAwMC8zcG9wc19NRDIwMDBfbWFmMDUudmNmLmd6IFxuIikKY2F0KCJiY2Z0b29scyBpbmRleCAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQyMDAwLzNwb3BzX01EMjAwMF9tYWYwNS52Y2YuZ3ogXG4iKQoKc2luayhOVUxMKQpgYGAKCgoKCgojIyBSVU4gY3Z0ayB3aXRoIHRoZSBuZXcgTUQyMDAwIHZjZiBmaWxlIAogKigzNTEsODIwIGxvY2kpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKY292czwtZGF0YS5mcmFtZSgpClZhcmlhbmNlPC1kYXRhLmZyYW1lKCkKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICBjb3Y8LXJlYWQuY3N2KHBhc3RlMCgiLi4vY3Z0a19hbmFseXNpcy9NRDIwMDBfM3BvcHNfbWFmMDVfdGVtcF9jb3ZfbWF0cml4XyIscG9wc1twXSwiXzFtLmNzdiIpKQogICAgY2k8LXJlYWQuY3N2KHBhc3RlMCgiLi4vY3Z0a19hbmFseXNpcy9NRDIwMDBfM3BvcHNfbWFmMDVfIixwb3BzW3BdLCJfQ292X0NJc19ib290c3RyYXA1MDAwXzFtd2luZG93LmNzdiIpKQogICAgY2k8LWNpWywtMV0KICAgIG1hdDE8LWNvdlsxOjMsXQogICAgbWF0MjwtY292WzQ6NixdCiAgICBjb3ZkZjwtZGF0YS5mcmFtZSgpCiAgICBrPTEKICAgIGZvciAoaSBpbiAxOm5yb3cobWF0MSkpewogICAgICAgIGZvciAoaiBpbiAxOm5jb2wobWF0MSkpewogICAgICAgICAgICBjb3ZkZltrLDFdPC1tYXQyW2ksal0KICAgICAgICAgICAgY292ZGZbaywyXTwtbWF0MVtpLGpdCiAgICAgICAgICAgIGs9aysxCiAgICB9fQogICAgY29sbmFtZXMoY292ZGYpPC1jKCJsYWJlbCIsInZhbHVlIikKICAgIGNvdmRmJHZhbHVlPC1hcy5udW1lcmljKGNvdmRmJHZhbHVlKQogICAgY292YXI8LWNvdmRmW2dyZXAoImNvdiIsY292ZGYkbGFiZWwpLF0KICAgIHZhcnM8LWNvdmRmW2dyZXAoInZhciIsY292ZGYkbGFiZWwpLF0KICAgIAogICAgI3JlbW92ZSB0aGUgcmVkdW5kYW50IHZhbHVlcwogICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgaWYgKHBvcHNbcF09PSJTUyIpIGNvdmFyPC1jb3ZhcltjKDEsMiw0KSxdCiAgICAgICAgCiAgICAjYXNzaWduIHRoZSBzdGFydGluZyB0aW1lIHBlcmlvZCBhbmQgY292ZXJpbmcgcGVyaW9kIHZhbHVlcwogICAgY292YXIkeWVhcjwtYygxLDIsMikKICAgIGNvdmFyJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgICAgICAKICAgIHZhcnMkeWVhcjwtYygiMTk5MS0xOTk2IiwiMTk5Ni0yMDA2IiwiMjAwNi0yMDE3IikKICAgICAgICAKICAgICNhc3NpZ24gcG9wdWxhdGlvbiBuYW1lCiAgICBjb3ZhciRsb2NhdGlvbjwtcG9wc1twXQogICAgdmFycyRsb2NhdGlvbjwtcG9wc1twXQogICAgICAgIAogICAgI2F0dGFjaCBjaSBpbmZvCiAgICBjb3ZhciRjaV9sPC1hcy5udW1lcmljKGMoY2lbMSwyXSwgY2lbMSwzXSxjaVsyLDNdKSkKICAgIGNvdmFyJGNpX3U8LWFzLm51bWVyaWMoYyhjaVs0LDJdLCBjaVs0LDNdLGNpWzUsM10pKQogICAgICAgIAogICAgI2NvbWJpbmUgaW4gdG8gb25lIG1hdHJpeAogICAgY292czwtcmJpbmQoY292cywgY292YXIpCiAgICBWYXJpYW5jZTwtcmJpbmQoVmFyaWFuY2UsIHZhcnMpCn0KVmFyaWFuY2UkZGVwdGg8LSJNRDIwMDBfbmV3IgojVmFyTUQyMDAwPC1WYXJpYW5jZQp4dGV4dHM8LWMoIlx1MDM5NDE5OTEtMTk5NlxuIH4gXHUwMzk0MTk5Ni0yMDA2IiwgIlxuICB+IFx1MDM5NDIwMDYtMjAxNyIpCgpnZ3Bsb3QoZGF0YT1jb3ZzLCBhZXMoeD15ZWFyLCB5PXZhbHVlLCBjb2xvcj1sb2NhdGlvbiwgc2hhcGU9c2VyaWVzLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSkpKwogICAgICAgIGdlb21fcG9pbnQoc2l6ZT0zLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMSxwcmVzZXJ2ZSA9InRvdGFsIikpKwogICAgICAgIGdlb21fbGluZShkYXRhPWNvdnMsIGFlcyh4PXllYXIsIHk9dmFsdWUsY29sb3I9bG9jYXRpb24sIGdyb3VwPWludGVyYWN0aW9uKGxvY2F0aW9uLCBzZXJpZXMpKSwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICB5bGFiKCJDb3ZhcmlhbmNlIikreGxhYignJykrdGhlbWVfY2xhc3NpYygpK2dndGl0bGUoIk1heCBEZXB0aCA9IDIwMDAiKSsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNpX2wsIHltYXg9Y2lfdSksIHdpZHRoPS4yLCBzaXplPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMSxwcmVzZXJ2ZSA9InRvdGFsIikpKwogICAgICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygxNiwxNyksbGFiZWxzPWMoIjE5OTEtIiwiMTk5Ni0iKSkrCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMSwyKSwgbGFiZWxzPXh0ZXh0cykrCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xzW2MoMiwzLDEpXSkKZ2dzYXZlKHBhc3RlMCgiLi4vT3V0cHV0L0NPVl9hbmFseXNpcy9NRDIwMDBfbmV3VkNGX2NvdnMucG5nIiksd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCgpgYGAKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvTUQyMDAwX25ld1ZDRl9jb3ZzLnBuZykgIAoKIyMgUGxvdCByZXN1bHRzIGZyb20gTUQyMDAwIGZpbHRlcmVkIGRvd24gZnJvbSBNRDcwMDAwCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKY292czwtZGF0YS5mcmFtZSgpClZhcmlhbmNlPC1kYXRhLmZyYW1lKCkKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICAjY292YXJpYW5jZSBvdXRwdXQgZmlsZQogICAgY292PC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvTUQyMDAwX21hZjA1X3RlbXBfY292X21hdHJpeF8iLHBvcHNbcF0sIl8xTS5jc3YiKSkKICAgIGNvdjwtY292WywtMV0KICAgICNDSSBmaWxlCiAgICBjaTwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF9tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDBfMU13aW5kb3cuY3N2IikpCiAgICBjaTwtY2lbLC0xXQogICAgICAgIAogICAgI3Jlc2hhcGUgdGhlIG1hdHJpeAogICAgbWF0MTwtY292WzE6MyxdCiAgICBtYXQyPC1jb3ZbNDo2LF0KICAgICAgICAKICAgIGNvdmRmPC1kYXRhLmZyYW1lKCkKICAgIGs9MQogICAgZm9yIChpIGluIDE6bnJvdyhtYXQxKSl7CiAgICAgICAgZm9yIChqIGluIDE6bmNvbChtYXQxKSl7CiAgICAgICAgICAgIGNvdmRmW2ssMV08LW1hdDJbaSxqXQogICAgICAgICAgICBjb3ZkZltrLDJdPC1tYXQxW2ksal0KICAgICAgICAgICAgaz1rKzEKICAgICAgICB9CiAgICB9CiAgICBjb2xuYW1lcyhjb3ZkZik8LWMoImxhYmVsIiwidmFsdWUiKQogICAgY292ZGYkdmFsdWU8LWFzLm51bWVyaWMoY292ZGYkdmFsdWUpCiAgICBjb3ZhcjwtY292ZGZbZ3JlcCgiY292Iixjb3ZkZiRsYWJlbCksXQogICAgdmFyczwtY292ZGZbZ3JlcCgidmFyIixjb3ZkZiRsYWJlbCksXQogICAgICAgIAogICAgI3JlbW92ZSB0aGUgcmVkdW5kYW50IHZhbHVlcwogICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgaWYgKHBvcHNbcF09PSJTUyIpIGNvdmFyPC1jb3ZhcltjKDEsMiw0KSxdCiAgICAgICAgCiAgICAjYXNzaWduIHRoZSBzdGFydGluZyB0aW1lIHBlcmlvZCBhbmQgY292ZXJpbmcgcGVyaW9kIHZhbHVlcwogICAgY292YXIkeWVhcjwtYygxLDIsMikKICAgIGNvdmFyJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgICAgICAKICAgIHZhcnMkeWVhcjwtYygiMTk5MS0xOTk2IiwiMTk5Ni0yMDA2IiwiMjAwNi0yMDE3IikKICAgICN2YXJzJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgICAgICAKICAgICNhc3NpZ24gcG9wdWxhdGlvbiBuYW1lCiAgICBjb3ZhciRsb2NhdGlvbjwtcG9wc1twXQogICAgdmFycyRsb2NhdGlvbjwtcG9wc1twXQogICAgICAgIAogICAgI2F0dGFjaCBjaSBpbmZvCiAgICBjb3ZhciRjaV9sPC1hcy5udW1lcmljKGMoY2lbMSwyXSwgY2lbMSwzXSxjaVsyLDNdKSkKICAgIGNvdmFyJGNpX3U8LWFzLm51bWVyaWMoYyhjaVs0LDJdLCBjaVs0LDNdLGNpWzUsM10pKQogICAgICAgIAogICAgI2NvbWJpbmUgaW4gdG8gb25lIG1hdHJpeAogICAgY292czwtcmJpbmQoY292cywgY292YXIpCiAgICBWYXJpYW5jZTwtcmJpbmQoVmFyaWFuY2UsIHZhcnMpCn0KVmFyaWFuY2UkZGVwdGg8LSJNRDIwMDBfbWQ3ayIKVmFyTUQyMDAwX21kN2s8LVZhcmlhbmNlCnh0ZXh0czwtYygiXHUwMzk0MTk5MS0xOTk2XG4gfiBcdTAzOTQxOTk2LTIwMDYiLCAiXG4gIH4gXHUwMzk0MjAwNi0yMDE3IikKCmdncGxvdChkYXRhPWNvdnMsIGFlcyh4PXllYXIsIHk9dmFsdWUsIGNvbG9yPWxvY2F0aW9uLCBzaGFwZT1zZXJpZXMsIGdyb3VwPWludGVyYWN0aW9uKGxvY2F0aW9uLCBzZXJpZXMpKSkrCiAgICAgICAgZ2VvbV9wb2ludChzaXplPTMsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgZ2VvbV9saW5lKGRhdGE9Y292cywgYWVzKHg9eWVhciwgeT12YWx1ZSxjb2xvcj1sb2NhdGlvbiwgZ3JvdXA9aW50ZXJhY3Rpb24obG9jYXRpb24sIHNlcmllcykpLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMSxwcmVzZXJ2ZSA9InRvdGFsIikpKwogICAgICAgIHlsYWIoIkNvdmFyaWFuY2UiKSt4bGFiKCcnKSt0aGVtZV9jbGFzc2ljKCkrZ2d0aXRsZSgiTWF4IERlcHRoID0gMjAwMCAoZmlsdGVyZWQgZnJvbSA3SykiKSsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNpX2wsIHltYXg9Y2lfdSksIHdpZHRoPS4yLCBzaXplPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMSxwcmVzZXJ2ZSA9InRvdGFsIikpKwogICAgICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygxNiwxNyksbGFiZWxzPWMoIjE5OTEtIiwiMTk5Ni0iKSkrCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMSwyKSwgbGFiZWxzPXh0ZXh0cykrCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xzW2MoMiwzLDEpXSkKZ2dzYXZlKHBhc3RlMCgiLi4vT3V0cHV0L0NPVl9hbmFseXNpcy9NRDIwMDBfZmlsdGVyZWRGcm9tTUQ3MDAwX1ZDRl9jb3ZzLnBuZyIpLHdpZHRoID0gNC43LCBoZWlnaHQgPSAzLCBkcGk9MzAwKQoKYGBgCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL01EMjAwMF9maWx0ZXJlZEZyb21NRDcwMDBfVkNGX2NvdnMucG5nKQoKIyMgUGxvdCBjb3ZhcmlhY25lIHJlc3VsdHMgZnJvbSBuZXcgTUQzMDAwICgzIHBvcHMgb25seSwgMzg5ODE3IGxvY2kpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKY292czwtZGF0YS5mcmFtZSgpClZhcmlhbmNlPC1kYXRhLmZyYW1lKCkKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICBjb3Y8LXJlYWQuY3N2KHBhc3RlMCgiLi4vY3Z0a19hbmFseXNpcy9NRDMwMDBfM3BvcHNfbWFmMDVfdGVtcF9jb3ZfbWF0cml4XyIscG9wc1twXSwiXzEwMGsuY3N2IikpCiAgICBjb3Y8LWNvdlssLTFdCiAgICBjaTwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMzAwMF8zcG9wc19tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDBfMTAwa3dpbmRvdy5jc3YiKSkKICAgIGNpPC1jaVssLTFdCiAgICBtYXQxPC1jb3ZbMTozLF0KICAgIG1hdDI8LWNvdls0OjYsXQogICAgY292ZGY8LWRhdGEuZnJhbWUoKQogICAgaz0xCiAgICBmb3IgKGkgaW4gMTpucm93KG1hdDEpKXsKICAgICAgICBmb3IgKGogaW4gMTpuY29sKG1hdDEpKXsKICAgICAgICAgICAgY292ZGZbaywxXTwtbWF0MltpLGpdCiAgICAgICAgICAgIGNvdmRmW2ssMl08LW1hdDFbaSxqXQogICAgICAgICAgICBrPWsrMQogICAgICAgIH0KICAgIH0KICAgIGNvbG5hbWVzKGNvdmRmKTwtYygibGFiZWwiLCJ2YWx1ZSIpCiAgICBjb3ZkZiR2YWx1ZTwtYXMubnVtZXJpYyhjb3ZkZiR2YWx1ZSkKICAgIGNvdmFyPC1jb3ZkZltncmVwKCJjb3YiLGNvdmRmJGxhYmVsKSxdCiAgICB2YXJzPC1jb3ZkZltncmVwKCJ2YXIiLGNvdmRmJGxhYmVsKSxdCiAgICAgICAgCiAgICBpZiAocG9wc1twXSE9IlNTIikgY292YXI8LWNvdmFyWyFkdXBsaWNhdGVkKGNvdmFyWywgMl0pLF0gCiAgICBpZiAocG9wc1twXT09IlNTIikgY292YXI8LWNvdmFyW2MoMSwyLDQpLF0KICAgIGNvdmFyJHllYXI8LWMoMSwyLDIpCiAgICBjb3ZhciRzZXJpZXM8LWMoIjE5OTEiLCIxOTkxIiwiMTk5NiIpCiAgICB2YXJzJHllYXI8LWMoIjE5OTEtMTk5NiIsIjE5OTYtMjAwNiIsIjIwMDYtMjAxNyIpCiAgICBjb3ZhciRsb2NhdGlvbjwtcG9wc1twXQogICAgdmFycyRsb2NhdGlvbjwtcG9wc1twXQogICAgY292YXIkY2lfbDwtYXMubnVtZXJpYyhjKGNpWzEsMl0sIGNpWzEsM10sY2lbMiwzXSkpCiAgICBjb3ZhciRjaV91PC1hcy5udW1lcmljKGMoY2lbNCwyXSwgY2lbNCwzXSxjaVs1LDNdKSkKICAgIGNvdnM8LXJiaW5kKGNvdnMsIGNvdmFyKQogICAgVmFyaWFuY2U8LXJiaW5kKFZhcmlhbmNlLCB2YXJzKQp9ClZhcmlhbmNlJGRlcHRoPC0iTUQzMDAwX25ldyIKdmFyLnN1bW1hcnk8LXJiaW5kKFZhck1EMjAwMCxWYXJpYW5jZSkKeHRleHRzPC1jKCJcdTAzOTQxOTkxLTE5OTZcbiB+IFx1MDM5NDE5OTYtMjAwNiIsICJcbiAgfiBcdTAzOTQyMDA2LTIwMTciKQoKZ2dwbG90KGRhdGE9Y292cywgYWVzKHg9eWVhciwgeT12YWx1ZSwgY29sb3I9bG9jYXRpb24sIHNoYXBlPXNlcmllcywgZ3JvdXA9aW50ZXJhY3Rpb24obG9jYXRpb24sIHNlcmllcykpKSsKICAgICAgICBnZW9tX3BvaW50KHNpemU9MywgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBnZW9tX2xpbmUoZGF0YT1jb3ZzLCBhZXMoeD15ZWFyLCB5PXZhbHVlLGNvbG9yPWxvY2F0aW9uLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKCJNYXggRGVwdGggPSAzMDAwIikrCiAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSsKICAgICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLGNvbG9yPSJncmF5NzAiLCBzaXplPTAuMykrCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1jaV9sLCB5bWF4PWNpX3UpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMTYsMTcpLGxhYmVscz1jKCIxOTkxLSIsIjE5OTYtIikpKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDEsMiksIGxhYmVscz14dGV4dHMpKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMywxKV0pCmdnc2F2ZShwYXN0ZTAoIi4uL091dHB1dC9DT1ZfYW5hbHlzaXMvTUQzMDAwX25ld1ZDRl9jb3ZzLnBuZyIpLHdpZHRoID0gNC43LCBoZWlnaHQgPSAzLCBkcGk9MzAwKQogCmBgYAoKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvTUQzMDAwX25ld1ZDRl9jb3ZzLnBuZykKCiMjIFBsb3QgdGhlIHZhcmlhbmNlcyBvZiBuZXcgTUQyMDAwLCBNRDMwMDAgJiBvbGQgTUQyMDAwCiAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCnZhci5zdW1tYXJ5PC1yYmluZCh2YXIuc3VtbWFyeSxWYXJNRDIwMDBfbWQ3aykKCnNlcWNvbHM8LXNlcXVlbnRpYWxfaGNsKDUsIHBhbGV0dGU9IlJlZC1CbHVlIikKI3JldmVyc2UgdGhlIG9yZGVyCnNlcWNvbHM8LXJldihzZXFjb2xzKQpnZ3Bsb3QodmFyLnN1bW1hcnksIGFlcyh4PXllYXIsIHk9dmFsdWUsIGZpbGw9ZGVwdGgpKSsKICAgIGZhY2V0X3dyYXAofmxvY2F0aW9uLCBuY29sPTEpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjgpKSsKICAgIHRoZW1lX2J3KCkreWxhYigiVmFyaWFuY2UiKSt4bGFiKCcnKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yPSJncmF5MzAiLCBzaXplPTAuMykrCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9c2VxY29scywgbmFtZT0iTWF4IGRlcHRoIikKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WX2FuYWx5c2lzL3ZhcmlhbmNlc19ieU1heERlcHRoRmlsdGVyLnBuZyIsIHdpZHRoID0gNywgaGVpZ2h0PTYsIGRwaT0zMDApCgpgYGAKCiFbXSguLi9PdXRwdXQvQ09WX2FuYWx5c2lzL3ZhcmlhbmNlc19ieU1heERlcHRoRmlsdGVyLnBuZykKKiBWYXJpYW5jZXMgYXJlIG5lZ2F0aXZlIGF0IE1EMzAwMCAtPiBVc2UgTUQyMDAwCgoKCgoKIyBDcmVhdGUgcG9wdWxhdGlvbiB2Y2YgZmlsZXMgZm9yIG1hbnVhbCBDSSBjYWxjdWxhdGlvbgojIyBDcmVhdGUgYSBzY3JpcHQgdG8gcnVuIGJjZnRvb2xzCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNpbmsoIlN1YnNldF92Y2ZfYnlQb3Auc2giKQpjYXQoIiMhL2Jpbi9iYXNoIFxuIikKY2F0KCJiY2Z0b29scyB2aWV3IC1PeiAtUyBEYXRhL3BvcGluZm8vcHdzLnR4dCAtLXRocmVhZHMgMjQgIERhdGEvbmV3X3ZjZi9NRDIwMDAvM3BvcHMuTUQyMDAwX25ldy5tYWYwNS52Y2YuZ3ogPiBEYXRhL25ld192Y2YvTUQyMDAwLzNwb3BzX01EMjAwMF9taW40MTdfUFdTX21hZjA1LnZjZi5neiBcbiIpCgpjYXQoImJjZnRvb2xzIHZpZXcgLU96IC1TIERhdGEvcG9waW5mby9zcy50eHQgLS10aHJlYWRzIDI0ICBEYXRhL25ld192Y2YvTUQyMDAwLzNwb3BzLk1EMjAwMF9uZXcubWFmMDUudmNmLmd6ID4gRGF0YS9uZXdfdmNmL01EMjAwMC8zcG9wc19NRDIwMDBfbWluNDE3X1NTX21hZjA1LnZjZi5neiBcbiIpCmNhdCgiYmNmdG9vbHMgdmlldyAtT3ogLVMgRGF0YS9wb3BpbmZvL3RiLnR4dCAtLXRocmVhZHMgMjQgIERhdGEvbmV3X3ZjZi9NRDIwMDAvM3BvcHMuTUQyMDAwX25ldy5tYWYwNS52Y2YuZ3ogPiBEYXRhL25ld192Y2YvTUQyMDAwLzNwb3BzX01EMjAwMF9taW40MTdfVEJfbWFmMDUudmNmLmd6IFxuIikKc2luayhOVUxMKQpgYGAKCgojIyBSdW4gQ1ZUSyB3aXRob3V0IERpcGxvaWQgb3IgRGVwdGggYmlhcyBjb3JyZWN0aW9uIApgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKY292czE8LWRhdGEuZnJhbWUoKQpWYXJpYW5jZTE8LWRhdGEuZnJhbWUoKQpmb3IgKHAgaW4gMTogbGVuZ3RoKHBvcHMpKXsKICAgIGNvdjwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF9taW40MTdfbm9fZGlwbG9pZF9iaWFzQ29ycmVjdGlvbl90ZW1wX2Nvdl9tYXRyaXhfIixwb3BzW3BdLCIuY3N2IikpCiAgICBjb3Y8LWNvdlssLTFdCiAgICBtYXQxPC1jb3ZbMTozLF0KICAgIG1hdDI8LWNvdls0OjYsXQogICAgCiAgICBjb3ZkZjwtZGF0YS5mcmFtZSgpCiAgICBrPTEKICAgIGZvciAoaSBpbiAxOm5yb3cobWF0MSkpewogICAgICAgIGZvciAoaiBpbiAxOm5jb2wobWF0MSkpewogICAgICAgICAgICBjb3ZkZltrLDFdPC1tYXQyW2ksal0KICAgICAgICAgICAgY292ZGZbaywyXTwtbWF0MVtpLGpdCiAgICAgICAgICAgIGs9aysxCiAgICB9fQogICAgY29sbmFtZXMoY292ZGYpPC1jKCJsYWJlbCIsInZhbHVlIikKICAgIGNvdmRmJHZhbHVlPC1hcy5udW1lcmljKGNvdmRmJHZhbHVlKQogICAgY292YXI8LWNvdmRmW2dyZXAoImNvdiIsY292ZGYkbGFiZWwpLF0KICAgIHZhcnM8LWNvdmRmW2dyZXAoInZhciIsY292ZGYkbGFiZWwpLF0KICAgICAgICAKICAgIGlmIChwb3BzW3BdIT0iU1MiKSBjb3ZhcjwtY292YXJbIWR1cGxpY2F0ZWQoY292YXJbLCAyXSksXSAKICAgIGlmIChwb3BzW3BdPT0iU1MiKSBjb3ZhcjwtY292YXJbYygxLDIsNCksXQogICAgICAgIAogICAgY292YXIkeWVhcjwtYygxLDIsMikKICAgIGNvdmFyJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgIHZhcnMkeWVhcjwtYygiMTk5MS0xOTk2IiwiMTk5Ni0yMDA2IiwiMjAwNi0yMDE3IikKICAgIGNvdmFyJGxvY2F0aW9uPC1wb3BzW3BdCiAgICB2YXJzJGxvY2F0aW9uPC1wb3BzW3BdCiAgICBjb3ZzMTwtcmJpbmQoY292czEsIGNvdmFyKQogICAgVmFyaWFuY2UxPC1yYmluZChWYXJpYW5jZTEsIHZhcnMpCn0KVmFyaWFuY2UxJG1ldGhvZDwtIm5vX2RpcGxvaWRfY29ycmVjdGlvbiIKCmNvdnMyPC1kYXRhLmZyYW1lKCkKVmFyaWFuY2UyPC1kYXRhLmZyYW1lKCkKZm9yIChwIGluIDE6IGxlbmd0aChwb3BzKSl7CiAgICAjY292YXJpYW5jZSBvdXRwdXQgZmlsZQogICAgY292PC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvTUQyMDAwX21pbjQxN19ub19kZXB0aF9iaWFzQ29ycmVjdGlvbl90ZW1wX2Nvdl9tYXRyaXhfIixwb3BzW3BdLCIuY3N2IikpCiAgICBjb3Y8LWNvdlssLTFdCiAgICBtYXQxPC1jb3ZbMTozLF0KICAgIG1hdDI8LWNvdls0OjYsXQogICAgCiAgICBjb3ZkZjwtZGF0YS5mcmFtZSgpCiAgICBrPTEKICAgIGZvciAoaSBpbiAxOm5yb3cobWF0MSkpewogICAgICAgIGZvciAoaiBpbiAxOm5jb2wobWF0MSkpewogICAgICAgICAgICBjb3ZkZltrLDFdPC1tYXQyW2ksal0KICAgICAgICAgICAgY292ZGZbaywyXTwtbWF0MVtpLGpdCiAgICAgICAgICAgIGs9aysxCiAgICB9fQogICAgY29sbmFtZXMoY292ZGYpPC1jKCJsYWJlbCIsInZhbHVlIikKICAgIGNvdmRmJHZhbHVlPC1hcy5udW1lcmljKGNvdmRmJHZhbHVlKQogICAgY292YXI8LWNvdmRmW2dyZXAoImNvdiIsY292ZGYkbGFiZWwpLF0KICAgIHZhcnM8LWNvdmRmW2dyZXAoInZhciIsY292ZGYkbGFiZWwpLF0KICAgICAgICAKICAgIGlmIChwb3BzW3BdIT0iU1MiKSBjb3ZhcjwtY292YXJbIWR1cGxpY2F0ZWQoY292YXJbLCAyXSksXSAKICAgIGlmIChwb3BzW3BdPT0iU1MiKSBjb3ZhcjwtY292YXJbYygxLDIsNCksXQogICAgICAgIAogICAgY292YXIkeWVhcjwtYygxLDIsMikKICAgIGNvdmFyJHNlcmllczwtYygiMTk5MSIsIjE5OTEiLCIxOTk2IikKICAgIHZhcnMkeWVhcjwtYygiMTk5MS0xOTk2IiwiMTk5Ni0yMDA2IiwiMjAwNi0yMDE3IikKICAgIGNvdmFyJGxvY2F0aW9uPC1wb3BzW3BdCiAgICB2YXJzJGxvY2F0aW9uPC1wb3BzW3BdCiAgICBjb3ZzMjwtcmJpbmQoY292czIsIGNvdmFyKQogICAgVmFyaWFuY2UyPC1yYmluZChWYXJpYW5jZTIsIHZhcnMpCn0KVmFyaWFuY2UyJG1ldGhvZDwtIm5vX2RlcHRoX2NvcnJlY3Rpb24iCgpjb3ZzMzwtZGF0YS5mcmFtZSgpClZhcmlhbmNlMzwtZGF0YS5mcmFtZSgpCmZvciAocCBpbiAxOiBsZW5ndGgocG9wcykpewogICAgI2NvdmFyaWFuY2Ugb3V0cHV0IGZpbGUKICAgIGNvdjwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF9taW40MTdfbm9fYmlhc0NvcnJlY3Rpb25zX3RlbXBfY292X21hdHJpeF8iLHBvcHNbcF0sIi5jc3YiKSkKICAgIGNvdjwtY292WywtMV0KICAgIG1hdDE8LWNvdlsxOjMsXQogICAgbWF0MjwtY292WzQ6NixdCiAgICAKICAgIGNvdmRmPC1kYXRhLmZyYW1lKCkKICAgIGs9MQogICAgZm9yIChpIGluIDE6bnJvdyhtYXQxKSl7CiAgICAgICAgZm9yIChqIGluIDE6bmNvbChtYXQxKSl7CiAgICAgICAgICAgIGNvdmRmW2ssMV08LW1hdDJbaSxqXQogICAgICAgICAgICBjb3ZkZltrLDJdPC1tYXQxW2ksal0KICAgICAgICAgICAgaz1rKzEKICAgIH19CiAgICBjb2xuYW1lcyhjb3ZkZik8LWMoImxhYmVsIiwidmFsdWUiKQogICAgY292ZGYkdmFsdWU8LWFzLm51bWVyaWMoY292ZGYkdmFsdWUpCiAgICBjb3ZhcjwtY292ZGZbZ3JlcCgiY292Iixjb3ZkZiRsYWJlbCksXQogICAgdmFyczwtY292ZGZbZ3JlcCgidmFyIixjb3ZkZiRsYWJlbCksXQogICAgICAgIAogICAgaWYgKHBvcHNbcF0hPSJTUyIpIGNvdmFyPC1jb3ZhclshZHVwbGljYXRlZChjb3ZhclssIDJdKSxdIAogICAgaWYgKHBvcHNbcF09PSJTUyIpIGNvdmFyPC1jb3ZhcltjKDEsMiw0KSxdCiAgICAgICAgCiAgICBjb3ZhciR5ZWFyPC1jKDEsMiwyKQogICAgY292YXIkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgdmFycyR5ZWFyPC1jKCIxOTkxLTE5OTYiLCIxOTk2LTIwMDYiLCIyMDA2LTIwMTciKQogICAgY292YXIkbG9jYXRpb248LXBvcHNbcF0KICAgIHZhcnMkbG9jYXRpb248LXBvcHNbcF0KICAgIGNvdnMzPC1yYmluZChjb3ZzMywgY292YXIpCiAgICBWYXJpYW5jZTM8LXJiaW5kKFZhcmlhbmNlMywgdmFycykKfQpWYXJpYW5jZTMkbWV0aG9kPC0ibm9fY29ycmVjdGlvbnMiClZhcmlhbmNlX2FsbDwtcmJpbmQoVmFyaWFuY2UxLCBWYXJpYW5jZTIsIFZhcmlhbmNlMykKCmNvdnMxJG1ldGhvZDwtIm5vX2RpcGxvaWRfY29ycmVjdGlvbiIKY292czIkbWV0aG9kPC0ibm9fZGVwdGhfY29ycmVjdGlvbiIKY292czMkbWV0aG9kPC0ibm9fY29ycmVjdGlvbnMiCgp4dGV4dHMyPC1jKCJcdTAzOTQnOTEtJzk2XG4gfiBcdTAzOTQnOTYtJzA2IiwgIlx1MDM5NCc5Ni0nMDZcbiAgfiBcdTAzOTQnMDYtJzE3IiwgIlx1MDM5NCc5MS0nOTZcbiAgfiBcdTAzOTQnMDYtJzE3IikKCmNvdnNfYWxsPC1yYmluZChjb3ZzMSxjb3ZzMiwgY292czMpCmNvdnNfYWxsJHRpbWU8LXJlcChjKCJjb3YxMiIsImNvdjEzIiwiY292MjMiKSwgOSkKCmdncGxvdChkYXRhPWNvdnNfYWxsLCBhZXMoeD10aW1lLCB5PXZhbHVlLCBjb2xvcj1sb2NhdGlvbiwgc2hhcGU9bWV0aG9kKSkrCiAgICAgICAgZ2VvbV9wb2ludChzaXplPTMsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKSsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9OSkpKwogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgICAgICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz14dGV4dHMyKSsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMywxKV0pKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygxLjUsMi41KSwgY29sb3I9ImdyYXkiLCBzaXplPTAuMikKZ2dzYXZlKCIuLi9PdXRwdXQvQ09WL3NlbnNpdGl2aXR5X2FuYWx5c2lzX2NvdnNfbm9fYmlhc19jb3JyZWN0aW9ucy5wbmciLCB3aWR0aCA9IDcsIGhlaWdodD02LCBkcGk9MzAwKQoKI3dpdGggYWxsIGNvcnJlY3Rpb25zCmNvdnM8LWRhdGEuZnJhbWUoKQpWYXJpYW5jZTwtZGF0YS5mcmFtZSgpCmZvciAocCBpbiAxOiBsZW5ndGgocG9wcykpewogICAgI2NvdmFyaWFuY2Ugb3V0cHV0IGZpbGUKICAgIGNvdjwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF8zcG9wc19tYWYwNV90ZW1wX2Nvdl9tYXRyaXhfIixwb3BzW3BdLCJfMTAway5jc3YiKSkKICAgIGNvdjwtY292WywtMV0KICAgICNDSSBmaWxlCiAgICBjaTwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF8zcG9wc19tYWYwNV8iLHBvcHNbcF0sIl9Db3ZfQ0lzX2Jvb3RzdHJhcDUwMDBfMTAwa3dpbmRvdy5jc3YiKSkKICAgIGNpPC1jaVssLTFdCiAgICAgICAgCiAgICAjcmVzaGFwZSB0aGUgbWF0cml4CiAgICBtYXQxPC1jb3ZbMTozLF0KICAgIG1hdDI8LWNvdls0OjYsXQogICAgICAgIAogICAgY292ZGY8LWRhdGEuZnJhbWUoKQogICAgaz0xCiAgICBmb3IgKGkgaW4gMTpucm93KG1hdDEpKXsKICAgICAgICBmb3IgKGogaW4gMTpuY29sKG1hdDEpKXsKICAgICAgICAgICAgY292ZGZbaywxXTwtbWF0MltpLGpdCiAgICAgICAgICAgIGNvdmRmW2ssMl08LW1hdDFbaSxqXQogICAgICAgICAgICBrPWsrMQogICAgICAgIH0KICAgIH0KICAgIGNvbG5hbWVzKGNvdmRmKTwtYygibGFiZWwiLCJ2YWx1ZSIpCiAgICBjb3ZkZiR2YWx1ZTwtYXMubnVtZXJpYyhjb3ZkZiR2YWx1ZSkKICAgIGNvdmFyPC1jb3ZkZltncmVwKCJjb3YiLGNvdmRmJGxhYmVsKSxdCiAgICB2YXJzPC1jb3ZkZltncmVwKCJ2YXIiLGNvdmRmJGxhYmVsKSxdCiAgICAgICAgCiAgICAjcmVtb3ZlIHRoZSByZWR1bmRhbnQgdmFsdWVzCiAgICBpZiAocG9wc1twXSE9IlNTIikgY292YXI8LWNvdmFyWyFkdXBsaWNhdGVkKGNvdmFyWywgMl0pLF0gCiAgICBpZiAocG9wc1twXT09IlNTIikgY292YXI8LWNvdmFyW2MoMSwyLDQpLF0KICAgICAgICAKICAgICNhc3NpZ24gdGhlIHN0YXJ0aW5nIHRpbWUgcGVyaW9kIGFuZCBjb3ZlcmluZyBwZXJpb2QgdmFsdWVzCiAgICBjb3ZhciR5ZWFyPC1jKDEsMiwyKQogICAgY292YXIkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgICAgIAogICAgdmFycyR5ZWFyPC1jKCIxOTkxLTE5OTYiLCIxOTk2LTIwMDYiLCIyMDA2LTIwMTciKQogICAgI3ZhcnMkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgICAgIAogICAgI2Fzc2lnbiBwb3B1bGF0aW9uIG5hbWUKICAgIGNvdmFyJGxvY2F0aW9uPC1wb3BzW3BdCiAgICB2YXJzJGxvY2F0aW9uPC1wb3BzW3BdCiAgICAgICAgCiAgICAjYXR0YWNoIGNpIGluZm8KICAgIGNvdmFyJGNpX2w8LWFzLm51bWVyaWMoYyhjaVsxLDJdLCBjaVsxLDNdLGNpWzIsM10pKQogICAgY292YXIkY2lfdTwtYXMubnVtZXJpYyhjKGNpWzQsMl0sIGNpWzQsM10sY2lbNSwzXSkpCiAgICAgICAgCiAgICAjY29tYmluZSBpbiB0byBvbmUgbWF0cml4CiAgICBjb3ZzPC1yYmluZChjb3ZzLCBjb3ZhcikKICAgIFZhcmlhbmNlPC1yYmluZChWYXJpYW5jZSwgdmFycykKfQoKVmFyaWFuY2UkbWV0aG9kPC0iYm90aCBjb3JyZWN0aW9uIgpWYXJpYW5jZV9hbGw8LXJiaW5kKFZhcmlhbmNlX2FsbCwgVmFyaWFuY2UpCgpnZ3Bsb3QoVmFyaWFuY2VfYWxsLCBhZXMoeD15ZWFyLCB5PXZhbHVlLCBmaWxsPW1ldGhvZCkpKwogICAgZmFjZXRfd3JhcCh+bG9jYXRpb24sIG5jb2w9MSkrCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOCkpKwogICAgdGhlbWVfYncoKSt5bGFiKCdWYXJpYW5jZScpK3hsYWIoJycpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3I9ImdyYXkzMCIsIHNpemU9MC4zKSsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1zZXFjb2xzLCBuYW1lPSJCaWFzIGNvcnJlY3Rpb24gYXBwbGllZCIpCmdnc2F2ZSgiLi4vT3V0cHV0L0NPVl9hbmFseXNpcy9zZW5zaXRpdml0eV9hbmFseXNpc192YXJzX25vX2JpYXNfY29ycmVjdGlvbnMucG5nIiwgd2lkdGggPSA3LCBoZWlnaHQ9NiwgZHBpPTMwMCkKCmBgYAoKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvc2Vuc2l0aXZpdHlfYW5hbHlzaXNfdmFyc19ub19iaWFzX2NvcnJlY3Rpb25zLnBuZykKCiogQ2FsY3VsYXRlIENJcyB1c2luZyB0aGUgJ3N0YW5kYXJkJyBib290c3RyYXAgbWV0aG9kIGluIGN2dGsgdG8gYXZvaWQgYmVpbmcgb2ZmIGNlbnRlcgoKIyMgUGxvdHMgQ09WcyBhbmQgQ0lzIGZyb20gdGhlICdzdGFuZGFyZCcgYm9vdHN0cmFwIG1ldGhvZAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcG9wczwtYygiUFdTIiwiVEIiLCJTUyIpCmNvdnM8LWRhdGEuZnJhbWUoKQpmb3IgKHAgaW4gMTogbGVuZ3RoKHBvcHMpKXsKICAgICNjb3ZhcmlhbmNlIG91dHB1dCBmaWxlCiAgICBjb3Y8LXJlYWQuY3N2KHBhc3RlMCgiLi4vY3Z0a19hbmFseXNpcy9NRDIwMDBfM3BvcHNfbWFmMDVfdGVtcF9jb3ZfbWF0cml4XyIscG9wc1twXSwiXzEwMGsuY3N2IikpCiAgICBjb3Y8LWNvdlssLTFdCiAgICAgICAgCiAgICAjcmVzaGFwZSB0aGUgbWF0cml4CiAgICBtYXQxPC1jb3ZbMTozLF0KICAgIG1hdDI8LWNvdls0OjYsXQogICAgICAgIAogICAgY292ZGY8LWRhdGEuZnJhbWUoKQogICAgaz0xCiAgICBmb3IgKGkgaW4gMTpucm93KG1hdDEpKXsKICAgICAgICBmb3IgKGogaW4gMTpuY29sKG1hdDEpKXsKICAgICAgICAgICAgY292ZGZbaywxXTwtbWF0MltpLGpdCiAgICAgICAgICAgIGNvdmRmW2ssMl08LW1hdDFbaSxqXQogICAgICAgICAgICBrPWsrMQogICAgICAgIH0KICAgIH0KICAgIGNvbG5hbWVzKGNvdmRmKTwtYygibGFiZWwiLCJ2YWx1ZSIpCiAgICBjb3ZkZiR2YWx1ZTwtYXMubnVtZXJpYyhjb3ZkZiR2YWx1ZSkKICAgIGNvdmFyPC1jb3ZkZltncmVwKCJjb3YiLGNvdmRmJGxhYmVsKSxdCiAgICAgICAgCiAgICAjcmVtb3ZlIHRoZSByZWR1bmRhbnQgdmFsdWVzCiAgICBpZiAocG9wc1twXSE9IlNTIikgY292YXI8LWNvdmFyWyFkdXBsaWNhdGVkKGNvdmFyWywgMl0pLF0gCiAgICBpZiAocG9wc1twXT09IlNTIikgY292YXI8LWNvdmFyW2MoMSwyLDQpLF0KICAgICAgICAKICAgICNhc3NpZ24gdGhlIHN0YXJ0aW5nIHRpbWUgcGVyaW9kIGFuZCBjb3ZlcmluZyBwZXJpb2QgdmFsdWVzCiAgICBjb3ZhciR5ZWFyPC1jKDEsMiwyKQogICAgY292YXIkc2VyaWVzPC1jKCIxOTkxIiwiMTk5MSIsIjE5OTYiKQogICAgICAgIAogICAgI2Fzc2lnbiBwb3B1bGF0aW9uIG5hbWUKICAgIGNvdmFyJGxvY2F0aW9uPC1wb3BzW3BdCiAgICAKICAgICNjb21iaW5lIGluIHRvIG9uZSBtYXRyaXgKICAgIGNvdnM8LXJiaW5kKGNvdnMsIGNvdmFyKQp9Cgpjb3ZzJHRpbWU8LXJlcChjKCJjb3YxMiIsImNvdjEzIiwiY292MjMiKSwgMykKY29sbmFtZXMoY292cylbMl08LSJjb3YiCgojIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoY2FsY3VsYXRlZCBmcm9tIHRoZSAnc3RyYXBzJyByZXR1cm5lZCBmcm9tIGJvb3RzdHJhcF9jb3YyKCkgY2k9MS45NipzZChzdHJhcHMpKQp0aW1lPC1jKCJjb3YxMiIsImNvdjEzIiwiY292MjMiKQoKY292cyRjaTwtTkEKZm9yIChpIGluIDE6bGVuZ3RoKHBvcHMpKXsgIAogICAgIGlmIChpIT0zKXsKICAgICAgICBkZjwtcmVhZC5jc3YocGFzdGUwKCIuLi9jdnRrX2FuYWx5c2lzL01EMjAwMF8iLHBvcHNbaV0sIl9DSXNfMTAwa3dpbmRvdy5jc3YiKSwgaGVhZGVyPUYpCiAgICAgICAgY292cyRjaVtjb3ZzJGxvY2F0aW9uPT1wb3BzW2ldJnRpbWU9PSdjb3YxMiddPC1kZlsxLDJdCiAgICAgICAgY292cyRjaVtjb3ZzJGxvY2F0aW9uPT1wb3BzW2ldJnRpbWU9PSdjb3YxMyddPC1kZlsxLDNdCiAgICAgICAgY292cyRjaVtjb3ZzJGxvY2F0aW9uPT1wb3BzW2ldJnRpbWU9PSdjb3YyMyddPC1kZlsyLDNdCiAgICB9CiAgICBpZiAocD09MykgewogICAgICAgIGRmPC1yZWFkLmNzdihwYXN0ZTAoIi4uL2N2dGtfYW5hbHlzaXMvTUQyMDAwXyIscG9wc1tpXSwiX0NJc18xMDBrd2luZG93LmNzdiIpLCBoZWFkZXI9RikKICAgICAgICBjb3ZzJGNpW2NvdnMkbG9jYXRpb249PXBvcHNbaV0mdGltZT09J2NvdjIzJ108LWRmWzEsMl0gCiAgICB9Cn0KCnh0ZXh0czwtYygiXHUwMzk0MTk5MS0xOTk2XG4gfiBcdTAzOTQxOTk2LTIwMDYiLCAiXG4gIH4gXHUwMzk0MjAwNi0yMDE3IikKCmdncGxvdChkYXRhPWNvdnMsIGFlcyh4PXllYXIsIHk9Y292LCBjb2xvcj1sb2NhdGlvbiwgc2hhcGU9c2VyaWVzLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSkpKwogICAgICAgIGdlb21fcG9pbnQoc2l6ZT0zLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMSxwcmVzZXJ2ZSA9InRvdGFsIikpKwogICAgICAgIGdlb21fbGluZShkYXRhPWNvdnMsIGFlcyh4PXllYXIsIHk9Y292LGNvbG9yPWxvY2F0aW9uLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKSsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNvdi1jaSwgeW1heD1jb3YrY2kpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMTYsMTcpLGxhYmVscz1jKCJcdTAzOTQnOTEtJzk2fiIsIlx1MDM5NCc5Ni0nMDZ+IikpKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDEsMiksIGxhYmVscz14dGV4dHMpKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29sc1tjKDIsMywxKV0pK3lsaW0oLTAuMDAzNywwLjAwMTMpCmdnc2F2ZShwYXN0ZTAoIi4uL091dHB1dC9DT1ZfYW5hbHlzaXMvM1BvcHNfcGxvdDEucG5nIiksd2lkdGggPSA0LjcsIGhlaWdodCA9IDMsIGRwaT0zMDApCiAgICAKY292cyR0aW1lPC1mYWN0b3IoY292cyR0aW1lLCBsZXZlbHM9YygiY292MTIiLCJjb3YyMyIsImNvdjEzIikpCiN4dGV4dHM8LWMoIlx1MDM5NDE5OTEtMTk5NlxuIH4gXHUwMzk0MTk5Ni0yMDA2IiwgIlx1MDM5NDE5OTYtMjAwNlxuICB+IFx1MDM5NDIwMDYtMjAxNyIsICJcdTAzOTQxOTkxLTE5OTZcbiAgfiBcdTAzOTQyMDA2LTIwMTciKQp4dGV4dHM8LWMoIlx1MDM5NCc5MS0nOTZcbiB+IFx1MDM5NCc5Ni0nMDYiLCAiXHUwMzk0Jzk2LScwNlxuICB+IFx1MDM5NCcwNi0nMTciLCAiXHUwMzk0JzkxLSc5NlxuICB+IFx1MDM5NCcwNi0nMTciKQoKZ2dwbG90KGRhdGE9Y292cywgYWVzKHg9dGltZSwgeT1jb3YsIGNvbG9yPWxvY2F0aW9uKSkrCiAgICAgICAgZ2VvbV9wb2ludChzaXplPTMsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgI2dlb21fbGluZShkYXRhPWNvdnMsIGFlcyh4PXllYXIsIHk9Y292LGNvbG9yPWxvY2F0aW9uLCBncm91cD1pbnRlcmFjdGlvbihsb2NhdGlvbiwgc2VyaWVzKSksIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4xLHByZXNlcnZlID0idG90YWwiKSkrCiAgICAgICAgeWxhYigiQ292YXJpYW5jZSIpK3hsYWIoJycpK3RoZW1lX2NsYXNzaWMoKSsKICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9OSkpKwogICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsY29sb3I9ImdyYXk3MCIsIHNpemU9MC4zKSsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWNvdi1jaSwgeW1heD1jb3YrY2kpLCB3aWR0aD0uMiwgc2l6ZT0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjEscHJlc2VydmUgPSJ0b3RhbCIpKSsKICAgICAgICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz14dGV4dHMpKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xzW2MoMiwzLDEpXSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjKDEuNSwyLjUpLCBjb2xvcj0iZ3JheSIsIHNpemU9MC4yKSt5bGltKC0wLjAwMzgsMC4wMDE0KQpnZ3NhdmUocGFzdGUwKCIuLi9PdXRwdXQvQ09WX2FuYWx5c2lzLzNQb3BzX3Bsb3QyLnBuZyIpLHdpZHRoID0gNC41NywgaGVpZ2h0ID0gMywgZHBpPTMwMCkKCmBgYAoKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvM1BvcHNfcGxvdDEucG5nKQoKIVtdKC4uL091dHB1dC9DT1ZfYW5hbHlzaXMvM1BvcHNfcGxvdDIucG5nKQoqIENvbnRpbnVlIHRvIENPVl9BbmFseXNpczEgJiBDT1ZfQW5hbHlzaXMyLlJtZA==